正在构建 json 响应。 NodeJS 发送空响应

Constructing json response. NodeJS send empty response

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

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.then 的异步性质上。你看, JSON.stringifyres.end 在两个 promise 都被 resolve 之前被调用了。要仅在获取所有数据时发送响应,您必须使用 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()});
    });
});

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

您需要确保在回复响应之前等待所有承诺解决,这实际上需要嵌套 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);
    });
});

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

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