I have this code where I want to send a response containing data that I get by requesting the database multiple times. I don't understand why it sends an 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;
The problem is in asynchronous nature of Promise.then
. You see, JSON.stringify
and res.end
is called before both of the promises will be resolved. To send the response only when all the data are fetched you have to use Promise.all
method.
Here is an example of how it could be done:
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()});
});
});
The database calls are asynchronous. They are returning promises and you are appending the then
functions, but the way javascript runs, the function is calling getTagType
and getSpecie
and then sending the response with res.end()
before the promises resolve and the db call is over.
You need to make sure you wait for all the promises to resolve before replying with the response, this essentially calls for nesting the then()
functions.
Like so:
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);
});
});
This function will return immediately, but won't call res.end()
until the database calls are completed.
This code gets cleaner once async/await
is added to the language :)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.