用于在nodejs中放置回调的语法和方法

时间:2015-01-05 01:42:35

标签: javascript node.js foreach callback

我使用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函数吗?

总之,

  1. res.send(quotes)循环完成后如何使用forEach
  2. 是否可以将回调(例如在forEach循环之后执行的回调)附加到对象上?我可以附加什么回调?要明确的是,“回调”的想法是什么?对我来说意味着事件循环将在附加回调的函数/对象完成执行后调用它。
  3. 感谢您的帮助!

1 个答案:

答案 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);
});

(未经测试的代码)。