【问题标题】:How to simplify deep nested promises如何简化深层嵌套的 Promise
【发布时间】:2015-11-13 00:37:10
【问题描述】:

我遇到了一种情况,我需要在 then() 中的每个“else”子句处中断,这看起来并不比嵌套回调更好,这是一个登录过程:

User.findOne({
    username: username
}).exec()
    .then(user => {
        if (user) {
            return user.verifyPassAsync()
                .then(matched => {
                    if (matched) {
                        return User.getBriefProfile(username))
                            .then(emp => {
                                if (emp) {
                                    return saveToSession(emp);
                                } else {
                                    //return 
                                }})
                    } else {
                        //return ...
                    }})
        } else {
        // return false
        }
    })

有什么方法可以简化这个吗?

【问题讨论】:

  • 那些 else 块到底是做什么的?
  • @Bergi 实际上,根据我的回答中的 cmets,OP 不知道在 elses 中返回什么。

标签: javascript promise ecmascript-6 bluebird es6-promise


【解决方案1】:

并非如此,因为您不是(仅)在这里嵌套承诺,而是条件。如果使用 async/await (ES7) 编写,您的函数将如下所示

var user = await User.findOne({username}).exec();
if (user) {
    var matched = await user.verifyPassAsync();
    if (matched) {
        var emp = await User.getBriefProfile(username);
        if (emp) {
            return saveToSession(emp);
        } else {
            // return …;
        }
    } else {
        // return …;
    }
} else {
    // return …;
}

如您所见,嵌套是您的程序所固有的。虽然它已经有点简化了(then 调用没有嵌套),您现在可以使用 Promise.coroutine 和 ES6 生成器来完成此操作。

您最好的选择可能是在每个else 中给throw 一个错误,然后用它来线性化链,最后.catching 它。当然,如果你在每个 else 块中都做同样的事情,那么你也可以写

var user = await User.findOne({username}).exec();
if (user)
    var matched = await user.verifyPassAsync();
if (matched)
    var emp = await User.getBriefProfile(username);
if (emp) {
    return saveToSession(emp);
else
    // return …;

这很容易转换回then 回调:

User.findOne({username: username}).exec()
.then(user =>
    user && user.verifyPassAsync()
).then(matched =>
    matched && User.getBriefProfile(username);
).then(emp =>
    emp ? saveToSession(emp) : …;
);

【讨论】:

  • 不要忘记上一个示例中的returns。
  • 比我原来的要好得多,尽管我的第一次尝试是早早打破,但你的例子改变了我的想法。另一个问题希望你不介意,then() 函数接受一个值并返回一个 Promise 对吗?如果在 else 分支中,我想返回 false,我应该使用“return false”,还是使用 Promise.resolve(false) 包装它?还是其他方式?
  • @loganfsmyth:完成:-)
  • @Sawyer:对。 then 回调不需要返回承诺,任何正常值(false)也可以。它将自动包装。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-04
  • 2021-05-22
  • 1970-01-01
  • 2016-01-12
  • 2016-03-01
  • 2019-01-01
  • 2020-12-10
相关资源
最近更新 更多