Цепочка произвольного числа обещаний в Q

Я хочу отправить HTTP-запрос N раз. Я хочу в конечном итоге получить информацию о результатах каждого из этих запросов.

Запуск функции запроса один раз прекрасно работает. Вот функция HTTP-запроса с использованием Q.defer():

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(результаты) печатается до того, как я получаю журналы от обратного вызова 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 (в моем исходном примере) в массиве?

2 ответа

Решение

Это отвечает на обновленную часть вопроса:

var buildCalls = function() {

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

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

return Q.all(buildCalls());

Q имеет другие функции, помогающие в рабочих процессах на основе Promise. Метод, который вам нужно использовать, Q#all, Если у вас есть массив обещаний, и вы хотите вызвать функцию, когда все они успешно выполнены, вы делаете

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

После того, как все обещания запроса выполнены, success_callback называется. Если кто-то из них отвергает, failure_callback называется сразу.

Другие вопросы по тегам