我使用express库在nodejs中有以下http端点:
app.get("/api/stocks/lookup/:qry", function(req, res) {
getJson(lookupSearch(req.params.qry), function(json) {
var quotes = [];
und.forEach(json, function(d) {
getJson(quoteSearch(d.Symbol), function(j) {
quotes.push(j);
});
});
res.send(quotes); //how can I make this execute after the .forEach is finished?
});
});
在这里,getJson
看起来像这样:
var getJson = function(search, cb) {
http.request(search, function(response) {
var raw = '';
response.on('data', function(d) {
raw += d;
});
response.on('end', function() {
cb(JSON.parse(raw));
});
response.on('error', function(err) {
console.error(err);
});
}).end();
};
我知道为什么这不会起作用,因为getJson
内的http请求是异步的,所以res.send(quotes)
几乎会立即发回。那么,在res.send(quotes)
循环完成后如何才能发送forEach
。我可以将回调附加到forEach
函数吗?
总之,
res.send(quotes)
循环完成后如何使用forEach
。forEach
循环之后执行的回调)附加到对象上?我可以附加什么回调?要明确的是,“回调”的想法是什么?对我来说意味着事件循环将在附加回调的函数/对象完成执行后调用它。感谢您的帮助!
答案 0 :(得分:1)
将你的getJson转换成一个承诺是个好主意,因为承诺很好用。没有承诺,手动方式是保持对未完成请求的反击:
var outstanding = 0;
json.forEach(function(d) {
outstanding++;
getJson(quoteSearch(d.Symbol), function(j) {
quotes.push(j);
if (!--outstanding) {
res.send(quotes);
}
});
});
如果您确实采用了承诺方式,那么您将map
超过json
,并返回请求的承诺;然后,您可以在承诺数组上指定then
。如果您使用jQuery而不是自己的自制程序解决方案,例如,
var requests = json.map(function(d) {
return $.getJSON(quoteSearch(d.Symbol), function(j) {
quotes.push(j);
});
});
$.when(requests).then(function() {
res.send(quotes);
});
(未经测试的代码)。