多次异步调用后回调?

时间:2015-10-03 06:40:49

标签: javascript node.js asynchronous scope

我使用Gmail API在循环中检索邮件,并为每封邮件执行req.write()。每个api调用都有一个回调函数,但是如何知道整个集合何时完成,以便我可以结束响应?我尝试了以下但是注意到回调没有按照数组索引的顺序执行,所以我不能只做我注释掉的那一行。

for (var i = 0; i < messages.length; i++) {
            var message = messages[i];
            console.log('- %s', message.id);
            (function(e){
              var request = gmail.users.messages.get({
                  auth:auth,
                  id:message.id,
                  userId: 'me'
                }, function(err, response) {
                  if(err) {
                    console.log('API returned an error: ' +err);
                    return;
                  }
                  res.write(JSON.stringify(response,null,'\t'));
                  console.log(e);
                  //if(e==messages.length-1) res.end();
                }
              );
            })(i);
}

1 个答案:

答案 0 :(得分:2)

但是,你走在正确的轨道上。由于在循环完成之前你不会得到任何回调,你可以跟踪你得到多少回调以及它何时到达messages.length,你知道你已经完成了:< / p>
var completed = 0;
for (var i = 0; i < messages.length; i++) {
    var message = messages[i];
    console.log('- %s', message.id);
    var request = gmail.users.messages.get({
        auth: auth,
        id: message.id,
        userId: 'me'
    }, function(err, response) {
        if (err) {
            // Should increment and check `completed` here too,
            // not sure what you want to do though
            console.log('API returned an error: ' + err);
            return;
        }
        res.write(JSON.stringify(response, null, '\t'));
        if (++completed == messages.length) {
            res.end();
        }
    });
}

假设在此期间任何事情都不会改变messages(影响其长度)。如果该假设无效,您可以反转completed,将其称为pending,并在达到0时完成:

var pending = 0;
for (var i = 0; i < messages.length; i++) {
    var message = messages[i];
    console.log('- %s', message.id);
    var request = gmail.users.messages.get({
        auth: auth,
        id: message.id,
        userId: 'me'
    }, function(err, response) {
        if (err) {
            // Should decrement and check `pending` here too,
            // not sure what you want to do though
            console.log('API returned an error: ' + err);
            return;
        }
        res.write(JSON.stringify(response, null, '\t'));
        if (--pending === 0) {
            res.end();
        }
    });
    ++pending;
}