【问题标题】:Async waterfall equivalent with Q与 Q 等效的异步瀑布流
【发布时间】:2013-12-02 05:27:09
【问题描述】:

我只有一个页面,即帐户设置页面。在其中,我允许我的用户更新他们的头像(如果他们附加了图片),更改他们的电子邮件(如果它已从原始更改),并更改他们的名称和密码。

现在,我正在使用 async 的 waterfall 方法,但我将 async 换成 Q,因为我更喜欢语法(和 api)。我想知道这是否是我应该使用 Q 代替异步瀑布的方式。

我正在做这样的事情:

exports.settingsAccountPOST = function(req, res) {
  var doesEmailExist = function() {
    var deferred = Q.defer();

    User.findByEmail({
      email: req.body.email
    }, function(err, user) {
      if (err) {
        deferred.reject(err);
      } else {
        deferred.resolve(user);
      }
    });
    return deferred.promise;
  };

  var updateEmail = function(email) {
    var deferred = Q.defer();

    User.updateEmail({
      userId : req.session.user.id,
      email : req.body.email
    }, function(err, updated) {
      if (err) {
        deferred.reject(err);
      } else {
        deferred.resolve(updated);
      }
    });
    return deferred.promise;
  };

  var updateName = function() {
    var deferred = Q.defer();

    if (req.body.name) {
      User.updateName({
        userId: req.session.user.id,
        name: req.body.name
      }, function(err, updated) {
        if (err) {
          deferred.reject(err);
        } else {
          deferred.resolve(updated);
        }
      });
      return deferred.promise;
    }
  };

  doesEmailExist().then(function(email) {
    if (!email) {
      return(updateEmail(email));
    }
  }).then(function() {
    return(updateName())
  }).then(function() {
    res.redirect('/account')
  });
};

说使用的电子邮件地址有误。有没有办法将它“传递”到最终调用?用例:正确更新了密码,但电子邮件更新不起作用,所以我想向用户显示一个会话闪现,告诉他们他们正确更新了密码,但更新他们的电子邮件时出现了问题。

我正在查看文档,看来我可能需要使用:

.fin(function () {
});

这是正确的吗?如果是这样,我应该传递什么?只需将链中发生的错误推送到一个对象,然后遍历所有错误并将它们显示给用户?还是直接返回并显示错误?

【问题讨论】:

  • 两年后……我也遇到了类似的情况。异步瀑布与 Q 承诺。你对开关满意吗?您喜欢语法和 API,但在此过程中您还发现了其他东西吗?既然您显然都使用了这两种方法,如果可以选择,您现在更喜欢哪一种?我正在决定走哪条路……异步瀑布或 Q 用于顺序执行异步函数。
  • 他们都做同样的事情。 Async 是一个可靠的库。不过,最近我一直在使用蓝鸟。

标签: javascript asynchronous promise deferred q


【解决方案1】:

如果您使用Q.defer,您通常会做错事。

var findByEmail = Q.nbind(User.findByEmail, User);
var updateEmail = Q.nbind(User.updateEmail, User);
var updateName = Q.nbind(User.updateName, User);

//later on...

exports.settingsAccountPOST = function (req, res) {
    findByEmail({
        email: req.body.email
    })
    .then(function (user) {
        if (!user) {
            return updateEmail({
                userId: req.session.user.id,
                email: req.body.email
            });
        }
    })
    .then(function () {
        return updateName({
            userId: req.session.user.id,
            name: req.body.name
        })
    })
    .then(function () {
        res.redirect("/account");
    })
    .catch(function(e){
        //Handle any error
    });
};

【讨论】:

  • 老兄,很好。谢谢!如果我使用Q.defer,为什么我会做错事?我之前使用 denodeify 进行 db 调用,那么 nbind 和 this 有什么区别?在 repo 中阅读它们让我更加困惑。
  • @BobCobb denodeifynbind 的别名 - 它们是相同的功能。因为.defer 打破了承诺链,因此扼杀了使用承诺的任何好处。它应该只用于包装一些不返回承诺的 API - 但您可以使用denodeify。 Otoh 一些罕见的 API 不适用于 denodeify,在这种情况下您必须使用 defer。
  • 谢谢。如果它不满足其中一项要求,我如何拒绝错误(又名抛出它)。我知道我可以throw new Error('Error reason') 但它仍会尝试完成其余的方法。我只是希望它从一切中返回。
  • @BobCobb 如果你抛出错误,它不会尝试完成其余的方法,而是立即跳转到 catch 处理程序
  • @bob_cobb 两年后...我处于类似情况。异步瀑布与 Q 承诺。你对开关满意吗?您喜欢语法和 API,但在此过程中您还发现了其他东西吗?既然您显然都使用了这两种方法,如果可以选择,您现在更喜欢哪一种?我正在决定走哪条路……异步瀑布或 Q 用于顺序执行异步函数。
猜你喜欢
  • 2017-10-29
  • 2014-04-28
  • 2015-07-18
  • 2018-11-13
  • 2020-09-06
  • 2015-04-28
  • 1970-01-01
  • 2014-10-09
  • 2016-01-20
相关资源
最近更新 更多