处理承诺链中的错误

Handling Errors in A Chain of Promises

我正在使用 Q.js 作为 promises 库。以前,有这样的代码:

function X() {
    return Q.Promise(function(resolve, reject) {
        Users.find()
            .then(function(user) {
                Q.all([
                    getUserProfileInfo(user),
                    getUserSomethingElse(user)
                ])
                    .spread(function(profile, something) {
                        // do stuff

                        resolve();
                    })
                    .catch(function(err) {
                        // handle error for Q.all()

                        reject();
                    })
            })
            .catch(function(err) {
                // handle error for User.find()

                reject();
            });
    });
}

但现在我知道我可以用类似的东西删除嵌套:

function X() {
    return Q.Promise(function(resolve, reject) {
        return Users.find()
            .then(function(user) {
                return Q.all([
                    getUserProfileInfo(user),
                    getUserSomethingElse(user)
                ]);
            })
            .spread(function(profile, something) {
                // do stuff

                resolve();
            })
            .catch(function(err) {
                // now how do I differenciate between 
                // the errors from Users.find() and Q.all()?

                reject();
            });
    });
}

我拥有的底部(扁平化)版本的 "problem" 是如何区分 Users.find()Q.all() 的错误?或者一般来说,长 then 链中可能还有许多其他错误?

目前我可能会使用类似

的东西
function(err) {
    if (err.errors && err.statusCode) {
        // do something
    } else if (err.message) {
        // do something
    }
}

但这不是真的 "nice" 代码是吗?一定会有更好的办法?

您可以使用多个 catch 块,像这样

function X() {
    return Q.Promise(function(resolve, reject) {
        return Users.find()
            .catch(function(err) {
                 // Handle user finding error
                 throw new Error("Problem in finding users");
            })
            .then(function(user) {
                return Q.all([
                    getUserProfileInfo(user),
                    getUserSomethingElse(user)
                ]);
            })
            .spread(function(profile, something) {
                // do stuff

                resolve();
            })
            .catch(function(err) {
                reject();
            });
    });
}

现在,如果在查找用户时出现问题,将执行第一个 catch 块,并且由于您从中抛出一个 Error,它将到达下一个 [=11] =] 链中的块。如果 Users.find 中没有错误,那么控制将直接转到 then 块。