.each和回调

时间:2014-05-12 11:53:20

标签: javascript node.js asynchronous cheerio

我正在使用请求和cheerio节点模块来创建从网站获取一些数据。 我想获得一个项目列表,一旦这个列表完成,就调用一个异步函数:

request('http://myurl', function(req,res,data){
    var $ = cheerio.load(data);
    var List = [];

    $('.myItems').each(function(i, element){
        console.log( typeof $(this).text() )
        List.push($(this).text());
    });

   for (var i=0; i <  List.length; i++){
      // make an asynchronous call to a API
   }
});

我的问题是我如何等待列表完成,即我怎么知道.each函数已遍历所有项目?

我可以使用异步执行此操作吗?

由于

3 个答案:

答案 0 :(得分:12)

cheerio的.each功能是同步的(参见source)。因此,只要您在回调中不执行任何异步操作(问题中就是这种情况),就无需执行任何操作:在以下行中,循环将完成。


如果在循环中调用异步函数,最简洁和最简单的解决方案是使用Promise库。

以顺序方式(例如Bluebird):

var p = Promise.resolve();
$('.myItems').each(function(i, element){
    p = p.then(function(){ 
         // do something with $(this).text() and return a promise
    });
});
p.then(function(){
   // all asynchronous tasks are finished
});

如果不需要顺序请求(此处为Q示例):

Q.allSettled($('.myItems').map(function(){
   // return a promise
})).then(function(){
   // all asynchronous tasks are finished
});

答案 1 :(得分:1)

您可以使用async模块轻松处理这些异步任务。

具体而言async.eachasync.eachLimit如果您需要并发&gt; 1或async.eachSeries如果你想要一次一个地浏览数组中的项目。

答案 2 :(得分:1)

我必须承认我没有设法让DenysSéguret的解决方案正常工作(对于.each()循环中的异步调用) - “after”操作仍然在.each()循环完成之前发生,但是我发现了一种不同的方式,我希望它有所帮助:

var Promises = require('bluebird');

request('http://myurl', function(req,res,data){
    var $ = cheerio.load(data);
    var List = [];

    Promises
    // Use this to iterate serially
    .each($('.myItems').get(), function(el){
        console.log( typeof $(el).text() )
        List.push($(el).text());
    })
    // Use this if order of items is not important
    .map($('.myItems').get(), function(el){
        console.log( typeof $(el).text() )
        List.push($(el).text());
    }, {concurrency:1}) // Control how many items are processed at a time
    // When all of the above are done, following code will be executed
    .then(function(){
        for (var i=0; i <  List.length; i++){
            // make an asynchronous call to a API
        }
    });
});

在这个特定的代码示例中,看起来你可能正在映射函数中进行异步调用,但是你得到了要点......

地图:https://github.com/petkaantonov/bluebird/blob/master/API.md#mapfunction-mapper--object-options---promise

每个:https://github.com/petkaantonov/bluebird/blob/master/API.md#eachfunction-iterator---promise