【问题标题】:Bluebird promise-based request handler in Express returning errorExpress 返回错误中基于 Bluebird 承诺的请求处理程序
【发布时间】:2014-12-28 12:56:17
【问题描述】:

我正在使用 Express (4.x)、Redis (2.8) 和 Bluebird (2.x) - 需要将多个 Redis 调用串在一起以返回响应:

var promise = require('bluebird');
var redis   = require('redis');
var redis = redis.createClient(6379,process.env["REDIS_ENDPOINT"],{});
promise.promisifyAll(redis);

// GET

exports.inOffers = function (req, res) {
    return redis.smembersAsync('advertisers')
    .map(function(advId){
        console.log('advId',advId);
        return redis.smembersAsync('advertiser:'+advId+':inoffers')
            .map(function(inOfferId){
                console.log('offerId: ',inOfferId);
                return redis.hgetallAsync('advertiser:'+advId+':inoffer:'+inOfferId);
            })
    })
    .done(function(inOffers){
        console.log('InOffers: ',inOffers);
        res.json({inOffers: inOffers})
    })
    .catch(function(err){
        console.log((new Date).toUTCString()+" [ERROR] ", err);
        res.writeHead(500);
        res.end();
    });
};

根据日志,数据是从 Redis 正确收集的,但我收到以下错误,而不是响应:

/var/app/current/node_modules/bluebird/js/main/async.js:95 扔 res.e; ^ 错误:发送后无法设置标头。

有什么想法吗?我是蓝鸟新手,可能搞砸了……

【问题讨论】:

    标签: node.js express redis promise bluebird


    【解决方案1】:

    您应该将.done 替换为.then

    【讨论】:

      【解决方案2】:

      澄清一下,正如本杰明在下面指出的那样,您的问题是您试图在响应对象已经发送到客户端之后设置标头。我不确定是否有其他中间件正在返回响应,或者它是否与您那里的 .done/.catch 相关。我会尝试下面的代码来结束您的承诺链,尽管我不确定它是否会有所帮助。另一个提示 - 根据 bluebird 文档,您不需要使用“完成”,但如果您愿意,可以使用 (bluebird .done docs)。如果你使用 .done,它应该是你的 Promise 链中的最后一件事(尽管你可以在其上同时拥有已完成和已拒绝的处理程序,就像 .then 一样)。

      .done(function(inOffers){
          console.log('InOffers: ',inOffers);
          res.json({inOffers: inOffers})
      }, function(err){
          console.log((new Date).toUTCString()+" [ERROR] ", err);
          res.writeHead(500);
          res.end();
      });
      

      【讨论】:

      • 绝对不是问题。 OP 的问题不在于承诺 - 这就是它所说的 - 他已将标头发送到应用程序的其他地方,现在尝试再次发送它们(例如将内容类型设置为 JSON)。如果您删除该代码的 res/req 部分,它就可以工作。 .done 是 Promise 库的旧时代的产物,它没有检测到未处理的拒绝。
      • 我意识到问题是响应试图发送两次,我认为这可能与完成后的捕获有关,所以如果 res.json 中有错误,捕获可能被触发。我对其进行了更改,因此只能调用其中一种响应方法。我还花时间指出他不必使用 .done,而且 .done 之后的 .catch 并没有真正的意义。这没有意义,不是吗?
      • 不,但这很可能是他的真实代码,因为.done 返回undefined
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-18
      • 2017-04-02
      • 1970-01-01
      • 2014-07-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多