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



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

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.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()});
    });
});

数据库调用是异步的。它们正在返回promise,您正在附加then函数,但按照javascript的运行方式,该函数调用getTagTypegetSpecie,然后在promise解析和db调用结束之前用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);
    });
});

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

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

最新更新