【问题标题】:then Promise doesn't work那么 Promise 不起作用
【发布时间】:2015-07-22 16:20:21
【问题描述】:

我有这个代码用于通过数据库进行统计报告。

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,所以我永远无法得到 ​​p>

statistics.commented_questions

statistics.no_commented

先谢谢了!

【问题讨论】:

  • 您的models.Quiz.findAll() 呼叫可能收到错误响应?如果代码只是在某个点停止,那么您可能会遇到某种运行时错误,您需要添加足够的调试代码来查看错误的位置/内容。您可能还想用一些可以吸引可能真正了解您正在使用的 API 的人的东西来标记您的问题,因为这个问题可能特定于您如何使用这些 API。而且,您的标题可能应该更具体地说明您的代码失败的地方(再次吸引可能能够提供帮助的合适类型的人)。
  • 感谢您的建议!对不起我的英语。下次我会努力做得更好。
  • 我的 cmets 是关于这个问题的,而不仅仅是下次。您可以随时使用“编辑”链接来澄清或改进您的问题。
  • 你需要return你的(回调)函数的承诺!

标签: javascript express promise


【解决方案1】:

当将 Promise 链接在一起时,他们需要知道前一个 Promise 何时被拒绝或履行。在您当前的代码中,初始承诺永远不会返回值/承诺,而是调用异步函数。代码在 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 没有等待它,为什么它仍在更新信息。这是一个竞争条件,本质上,承诺就是胜利。

要将 Promise 正确地链接在一起,您需要将新的 Promise 返回到旧的 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);
};

如果您使用的 Node/IO 版本支持原生 Promise 对象,您可以利用这一点来发出并发请求,因为它们都不相互依赖。注意: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);
};

【讨论】:

  • 抱歉 Jason,我刚刚发布了你的最后一个代码。你的解决方案很聪明!!但是现在出现了一个新的错误,Promise 是未定义的。非常感谢您的帮助!
  • 我是否需要在 JSON 中进行其他声明?
  • @Jota 如上所述,Promise 仅在较新版本的 Node.js 或 IO.js 中可用。如果它不可用,您可以轻松地使用 Bluebird、Q、async 等来做类似的事情。关于您的其他问题,我不确定您在问什么。
  • 另一个问题是关于你的第二个建议。在这种情况下,当读取 Comment.length 时应用程序崩溃,并且错误显示“无法读取未定义的属性”。最后,我将尝试更新节点版本!谢谢!
  • @Jota 哦,我明白了。那是由于quizes 的结构。在不知道结构是什么样子的情况下,我无法回答这个问题(这将是一个不同的问题)。 :)
猜你喜欢
  • 1970-01-01
  • 2013-01-06
  • 1970-01-01
  • 2011-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-17
相关资源
最近更新 更多