那么承诺就行不通了

then Promise doesn't work

本文关键字:行不通 承诺      更新时间:2023-09-26

我有一个数据库统计报告的代码。

exports.calculate = function(req, res, next) {
    models.Quiz.count()
    .then(function(questions) {
        statistics.questions = questions;
        models.Comment.count().then(function(comments) {
            statistics.comments = comments;
            statistics.average_comments = (statistics.comments / statistics.questions).toFixed(2);
            models.Quiz.findAll({
                include:    [{model: models.Comment}]})
            .then(function(quizes) {
                for (index in quizes) {
                    if (quizes[index].Comment.length) {
                        statistics.commented_questions++;
                    } else {statistics.no_commented++;}
                };
            })
        })
    })
    .catch(function(error) {next(error)})
    .finally(function() {next()});      
};

它工作正常,直到SQL语句,但从不做循环for,所以我永远不能得到

statistics.commented_questions

statistics.no_commented

提前感谢!

当将承诺链接在一起时,它们需要知道前一个承诺何时被拒绝或履行。在你当前的代码中,初始的promise从来不返回一个值/promise,而是调用一个async函数。对于JS引擎来说,代码基本上是这样的:

exports.calculate = function(req, res, next) {
  models.Quiz.count()
    .then(function(questions) {
      statistics.questions = questions;
      // ASYNC FUNCS THAT ARE NEVER RETURNED
      // ...
      // functions in JS without an explicit return statement return nothing (essentially `undefined`)
    })
    .catch(function(error) {
      next(error)
    })
    .finally(function() {
      next()
    });
};

因此,在引擎等待初始承诺被完成/拒绝之后,它会为一个异步操作触发另一个承诺,该操作返回一个承诺,但不会将其返回到原始承诺链。默认情况下,原始承诺链接收undefined,然后将其传递给链中的下一个方法。在本例中,它将是finally方法。

你可能想知道为什么第二个承诺还在更新信息,如果它没有等待它。这是一个竞态条件,从本质上讲,promise是获胜的。

要正确地将承诺链接在一起,您需要将新承诺返回到旧承诺链中,如下所示:

exports.calculate = function(req, res, next) {
  models.Quiz.count().then(function(questions) {
    statistics.questions = questions;
    return models.Comment.count();
  }).then(function(comments) {
    statistics.comments = comments;
    statistics.average_comments = (statistics.comments / statistics.questions).toFixed(2);
    return models.Quiz.findAll({
      include: [{
        model: models.Comment
      }]
    });
  }).then(function(quizes) {
    for (index in quizes) {
      if (quizes[index].Comment.length) {
        statistics.commented_questions++;
      } else {
        statistics.no_commented++;
      }
    }
  }).catch(next).finally(next);
};

如果你使用的是支持本地Promise对象的Node/IO版本,你可以利用这一点来发出并发请求,因为它们都不依赖于彼此。注意:Promise API没有finally()方法,但我们可以使用then()的第二个参数来传递错误。

exports.calculate = function(req, res, next) {
  Promise.all([
    models.Quiz.count(),
    models.Comment.count(),
    models.Quiz.findAll({
      include: [{
        model: models.Comment
      }]
    })
  ]).then(function(results)
    // `results` is an array of [questions, comments, quizes]
    statistics.questions = results[0];
    statistics.comments = results[1];
    statistics.average_comments = (statistics.comments / statistics.questions).toFixed(2);
    for (index in results[2]) {
      if (results[2][index].Comment.length) {
        statistics.commented_questions++;
      } else {
        statistics.no_commented++;
      }
    }
  }).then(next, next);
};