【问题标题】:Have express.js send response from async callback让 express.js 从异步回调发送响应
【发布时间】:2015-06-01 06:09:57
【问题描述】:

我有一个非常简单的场景,在 Node / Express.js 中有一个 RESTful 端点,需要调用另一个 REST 服务并返回其结果。

我面临的麻烦是在 Express 方法中获得响应以发回适当的数据。

var express = require('express');
var app = express();

app.post('/test', function(req, res) {
    async.series([ function(callback) {
        var httpConfig = app.config.evaluateRuleService;
        logger.info("About to make request");
        // make an async call here
        require('../utils/http-wrapper/http').post(req.body, httpConfig,
                function(err, data) {
                    logger.info("still have res: " + res);
                    logger.info("Got response: " + data);
                    // data.isAuthorized is set by the service being invoked
                    callback(false, data);
                });
    } ],
    function(err, results) {
        logger.info("Inside collate method");
        // correctly gets invoked after async call completes
        // but res.json isn't sending anything to the client
        res.json({
            authorized : results.isAuthorized
        });
    })
    // Problem: The client is receiving the response before the async call completes
});

这是日志输出:

"Listening on port 8897","time":"2015-03-27T19:22:24.435Z","v":0}
"About to make request","time":"2015-03-27T19:22:30.608Z","v":0}
fetch() POST http://localhost:8897/test 
**<logs of the server method being invoked are printed out>** 
"still have res: [object Object]","time":"2015-03-27T19:22:30.616Z","v":0} 
"Got response: {\"isAuthorized\":true}","time":"2015-03-27T19:22:30.616Z","v":0}
"Inside collate method","time":"2015-03-27T19:22:30.617Z","v":0}

所以订单以一种令人满意的方式发生,但是,调用此端点的客户端看到返回的是一个空结果,而不是我试图在最后一个回调中发送到响应的预期 authorized : results.isAuthorized

非常感谢

使用解决方案编辑:

正如彼得和凯文指出的那样,有两个问题正在发生,认为响应发送得太早是误诊。

results对象确实是一个数组,我的相关索引是[0]。然后我需要将 String response 转换为 JSON 对象,以便能够访问我需要的字段。

解决这个问题的回调函数中的答案是:

function(err, results) {
    logger.info('Inside collate method');
    // Need to access array at appropriate index 
    logger.info('Authorize Response: ' + results[0]);
    // Need to parse the value at index 0 as a JSON object
    var authorizeResponse = JSON.parse(results[0]);
    res.json({
            authorized : authorizeResponse.isAuthorized
        });
}

【问题讨论】:

  • 我看不到您将 isAuthorized 传递给 async.series 回调的位置
  • 我稍微缩短了代码以使流程更加明显,并且该部分被裁剪了。我会更新它以使其清楚
  • 并且代码有效——调试它我知道results.isAuthorized 已适当填充,并且日志记录语句也支持这一点。问题是在调用 res.json({... 行之前将响应发送到客户端。
  • “问题是在调用 res.json({... 行之前将响应发送给客户端。” 这应该是不可能的,我认为您误诊了问题。此时results 更有可能没有isAuthorized 属性。
  • 您是否在 async.series 回调中记录了result?我希望它是一个数组。

标签: node.js asynchronous express


【解决方案1】:

您没有正确的 async.series 签名。最终回调的参数是error, arrayOfResults,因此您需要results[0].isAuthorized 才能获得正确的值。我的理论是您的代码生成对象{isAuthorized: undefined},因为结果数组没有isAuthorized 属性。然后将其序列化为 JSON 中的空对象,如下所示:

> JSON.stringify({isAuthorized: undefined})
'{}'

不过,时序和控制流程还可以。问题不在于响应发送得太早。

【讨论】:

  • 你在所有方面都是对的——results 对象是一个数组,引用results[0] 是我错的第一部分。那么你也正确地进行了我需要的普通字符串到对象的转换。我更新了我的答案,以显示合并并澄清未来可能看到此问题的人的误诊
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-19
相关资源
最近更新 更多