在Q中链接任意数量的承诺

时间:2013-06-07 05:04:29

标签: node.js q

我想发送N次HTTP请求。我想最终获得有关每个请求结果的信息。

运行请求函数一次很有效。这是使用Q.defer()的HTTP请求函数:

function runRequest() {
    var deferred = Q.defer(),
        start = (new Date).getTime(),
        req = HTTP.request(options, function(res) {
            var end = (new Date).getTime(),
            requestDetails = {
                reqStatus: res.statusCode,
                reqStart: start,
                reqEnd: end,
                duration: end - start
            }
            deferred.resolve(requestDetails);
        });
    req.on('error', function(e) {
        deferred.reject(e.message);
    });
    req.end();

    return deferred.promise;
}

如果我这样做,我会收到我期望的数据:

runRequest().then(function(requestDetails) {
    console.log('STATUS: ' + requestDetails.reqStatus);
    console.log('Duration: ' + requestDetails.duration);
    console.log('Start: ' + requestDetails.reqStart);
    console.log('End: ' + requestDetails.reqEnd);

}, function(error) {
    console.log('Problem with request: ' + error);
})
.done();

要迭代,我试图将其纳入for循环:

function iterateRequests() {
    var deferred = Q.defer();
    var reqResults = [];
    for (var iteration = 0; iteration < requests; iteration++) {
        runRequest()
        .then(function(requestDetails) {
            console.log('STATUS: ' + requestDetails.reqStatus);
            reqResults.push(requestDetails);
        }, function(error) {
            console.log('Problem with request: ' + error);
        });
    }
    deferred.resolve(reqResults);
    return deferred.promise;
}

然后我称之为:

iterateRequests()
.then(function(results) {
    console.log(results);
    console.log("in the success callback after iterateRequests");
}, function() {
    console.log("in the failure callback after iterateRequests");
})
.done();

我最终进入成功回调(即,它在“iterateRequests之后的成功回调”中记录)。但是,在我从runRequest()。then()回调获取日志之前打印了console.log(结果),它是一个空数组。

关于链接/迭代promise-return函数的任何想法或一些指导?

谢谢!

更新 跟进问题以回应@ abject_error的回答:

检查了Q.all。绝对看起来像我需要的。而且我正在使用的东西要简单得多。我做了一个简单的测试用例来帮助我弄清楚它是如何工作的:

var Q = require("q");

function returner(number) {
    var deferred = Q.defer();

    deferred.resolve(number);
    return deferred.promise;
}

function parent() {
    return Q.all([
        returner(1),
        returner(2),
        returner(4)
    ]);
}


parent()
.then(function(promises) {
    // works - promises gives me [1, 2, 4]
    console.log(promises);
});

所以,如果我事先知道需要调用它的次数(以及我要调用的函数),我就知道如何使用它。关于如何在数组中获得对返回者(在此示例中)或runRequest(在我的原始示例中)的动态调用次数的任何提示?

2 个答案:

答案 0 :(得分:7)

这回答了问题的更新部分:

var buildCalls = function() {

  var calls = [];
  for (var i in stories) {

    calls.push(myFunc(i));
  }
  return calls;
}

return Q.all(buildCalls());

答案 1 :(得分:5)

Q还有其他功能来帮助基于Promise的工作流程。您需要使用的方法是Q#all。如果您有一系列承诺,并且想要在所有成功完成后调用函数,那么您可以

Q.all(array_of_promises).then(success_callback, failure_callback);

在完成所有请求承诺后,将调用success_callback。如果任何拒绝,则会立即调用failure_callback