nodejs Q.all承诺函数调用本身

nodejs Q.all promises on function calling itself

本文关键字:函数调用 承诺 all nodejs      更新时间:2023-09-26

我需要发出一个请求来获取html列表,我需要扫描它并循环浏览它,并为找到的列表中的每一项发出更多请求,这些请求中可能有列表,依此类推,直到没有列表为止。

我需要一种方法来跟踪所有调用的请求,并在它们完成后调用另一个函数。棘手的是,对于HTML中的任何列表项,函数都会一遍又一遍地调用自己。

我遇到的问题是使用Q promise,它唯一等待的promise来自第一个请求,我不明白为什么假设节点像我认为的那样工作,请参阅代码:

var _ = require('underscore');
var request = require('request');
var allPromises = [];
var finalArray = [];
var start = function(id) {
  var deferred = Q.defer(); 
  request.get({
    url: 'http://www.example.com/id/' + id
  }, function() {
    _.each(body.items, function(index) {
      var item = this;
      finalArray.push(item);
      if(item.hasMore) {
        start(item.id);
      }
    }
    deferred.resolve();
  });
  allPromises.push(deferred.promise);
}
console.log('Starting');
start(1);
Q.all(allPromises).done(function (values) {
  console.log('All Done');
});

我想发生的是:

第一次调用1-starts()并创建第一个延迟的var
2-发出第一个请求,并将第一个创建的延迟变量推送到promise数组
3-Q.all被调用并等待

4-调用第一个请求的回调5-如果请求包含body.x,则使用新id再次调用start()
6-创建并推送新的promise,并提出新的请求
7-第一个承诺被解决

假设这只深入一级

8-第二个承诺得到解决
9-Q.all调用其回调

但在实践中,Q.all在第一个promise之后调用回调,即使在第一个promise被解析之前推送了第二个promise,它也不会等待任何其他promise。

为什么?我该怎么做?

Update忘记在请求回调中添加循环。

编辑问题的答案:

var request = require('request');
var finalArray = [];
var start = function(id) {
    var deferred = Q.defer();
    request.get({
        url: 'http://www.example.com/id/' + id
    }, function() {
        var subitems = [];
        _.each(body.items, function(index) {
            var item = this;
            finalArray.push(item);
            if(item.hasMore) {
                subitems.push(start(item.id));
            }
        }
        if (subitems.length) {
            deferred.resolve(Q.all(subitems)); // resolve result of Q.all
        } else {
            deferred.resolve();
        }
    });
    return deferred.promise;
}
start(1).done(function() {
    console.log('All Done');
});

@Bergi码

var request = require('request');
var start = function(id) {
    var deferred = Q.defer();
    request.get({
        url: 'http://www.example.com/id/' + id
    }, function(err, body) {
        if (err) deferred.reject(err);
        else deferred.resolve(body);
    });
    return deferred.promise.then(function(body) {
        var finalArray = [];
        return Q.all(_.map(body.items, function(index) {
            var item = this;
            finalArray.push(item);
            if(item.hasMore)
                return start(item.id);
            else
                return [];
        })).then(function(moreResults) {
            return finalArray.concat.apply(finalArray, moreResults);
        });
    });
}
start(1).then(function(finalArray) {
    console.log('All Done');
});