【问题标题】:Chaining an arbitrary number of promises in Q在 Q 中链接任意数量的 Promise
【发布时间】:2013-06-03 07:35:30
【问题描述】:

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

运行一次请求函数效果很好。下面是使用 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 之后的成功回调中”)。但是,console.log(results) 在我从 runRequest().then() 回调获取日志之前打印,它是一个空数组。

关于链接/迭代承诺返回函数的任何想法或一些指导?

谢谢!

更新 针对@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(在我的原始示例中)的动态调用次数的任何提示?

【问题讨论】:

    标签: node.js q


    【解决方案1】:

    Q 具有其他功能来帮助基于 Promise 的工作流程。您需要使用的方法是Q#all。如果你有一个 promise 数组,并且你想在 所有 都成功实现时调用一个函数,你可以这样做

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

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

    【讨论】:

    • 感谢 abject_error。看起来正是我需要的。有关如何在 array_of_promises 中获得动态数量的函数调用的任何建议?我在上面的问题中添加了一些进一步的解释。
    • @Domenic - 嗨,数组的大小是否有任何(合理的)限制 - Q 会在内部对其进行限制,这样它就不会超出可以在同时在机器上。例如,是否要对 10K 项进行批处理/限制?
    • 大多数异步操作都是由底层系统自然批处理或限制的,例如大多数网络将在一定数量后通过管道打开连接。
    【解决方案2】:

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

    var buildCalls = function() {
    
      var calls = [];
      for (var i in stories) {
    
        calls.push(myFunc(i));
      }
      return calls;
    }
    
    return Q.all(buildCalls());
    

    【讨论】:

    • 花了我一段时间才知道。感谢您的回答。这正是我所需要的。
    猜你喜欢
    • 2015-01-19
    • 2013-07-19
    • 1970-01-01
    • 1970-01-01
    • 2020-02-08
    • 1970-01-01
    • 2014-06-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多