【问题标题】:Constructing json response. NodeJS send empty response构造 json 响应。 NodeJS 发送空响应
【发布时间】:2017-04-29 23:39:55
【问题描述】:

我有这段代码,我想发送一个响应,其中包含我通过多次请求数据库获得的数据。我不明白为什么它会发送一个空响应。

var express = require('express'),
router = express.Router(),
database = require('../database');

router.get('/', function(req, res, next){

  res.writeHead(200, {"Content-Type": "application/json"});

    var ttt;
    var yyy;

    database.getTagType().then(function(data) {
        ttt = "pfff";
    });

    database.getSpecie().then(function(data) {
        yyy = "akkhhh";
    });

  var json = JSON.stringify({
    anObject: ttt, 
    anArray: yyy, 
  });
  res.end(json);

});

module.exports = router;

【问题讨论】:

  • Promise 是异步的,因此在您为响应创建 json 对象时尚未分配 tttyyy

标签: javascript json node.js httpresponse


【解决方案1】:

问题在于Promise.then 的异步性质。你看,JSON.stringifyres.end 在两个 promise 都被解决之前被调用。要仅在获取所有数据后发送响应,您必须使用 Promise.all 方法。

下面是一个例子:

router.get('/', function(req, res, next){
    var promises = [];

    promises.push(database.getTagType().then(function(data){
        return "pfff";
    }));

    promises.push(database.getSpecie().then(function(data) {
        return "akkhhh";
    }));

    Promise.all(promises).then(function(values) {
        // Actually, express can stringify response for us. Also it adds
        // correct "Content-Type" header.
        res.json({
            anObject: values[0], 
            anArray: values[1]
        });
    }).catch(function(error) {
        // Something went wrong. Let the error middleware deal with the problem.
        next(error);
        // Instead we can just send an error response, like so:
        // res.status(500).json({error: error.toString()});
    });
});

【讨论】:

  • 添加catch 块,因为使用您当前的代码,如果出现任何错误,用户将永远不会收到响应。
  • 你说得对,谢谢你的通知。我已经更新了答案。
【解决方案2】:

数据库调用是异步的。他们正在返回承诺,您正在附加 then 函数,但是 javascript 运行的方式是,该函数调用 getTagTypegetSpecie,然后使用 res.end() 发送响应承诺之前解决,db 调用结束。

您需要确保在回复响应之前等待所有承诺解决,这实质上需要嵌套then() 函数。

像这样:

router.get('/', function(req, res, next){

  res.writeHead(200, {"Content-Type": "application/json"});

    var tag = database.getTagType();
    // `tag` is now a promise

    var specie = database.getSpecie();
    // `specie` is a promise

    Promise.all([tag, specie]).then(function(values) {
    // this code is executed once both promises have resolved, the response has come back from the database

        var json = JSON.stringify({
            tag: values[0],
            specie: values[1]
        )};

        res.end(json);
    });
});

此函数将立即返回,但在数据库调用完成之前不会调用res.end()

一旦将async/await 添加到语言中,此代码就会变得更清晰:)

【讨论】:

  • @user2795508 您能否将答案标记为“已接受”,以便人们知道它已解决?应该是答案旁边的复选标记。
猜你喜欢
  • 2017-12-21
  • 1970-01-01
  • 1970-01-01
  • 2015-09-29
  • 2019-07-12
  • 2017-11-03
  • 1970-01-01
  • 2021-03-15
  • 2016-09-13
相关资源
最近更新 更多