javascript .each 和回调

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23608325/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 01:12:45  来源:igfitidea点击:

.each and callbacks

javascriptnode.jsasynchronouscheerio

提问by Spearfisher

I am using request and cheerio node modules to create get some data out of a website. I'd like to get a list of item and once this list is complete, call an asynchronous function:

我正在使用请求和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
   }
});

My question is how do I wait for the list to be completed, ie, how can I know than the .each function has looped through all the items?

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

Can I do this with async?

我可以用异步来做到这一点吗?

Thanks

谢谢

回答by Denys Séguret

The .eachfunction of cheerio is synchronous (see source). So as long as you do nothing asynchronous in the callback (which is the case in the question), you have nothing to do : at the following line the loop will be complete.

.eachCheerio的功能是同步的(见源码)。因此,只要您在回调中不执行任何异步操作(问题中就是这种情况),您就无事可做:在下一行,循环将完成。



If you docall asynchronous functions in the loop, the cleanest and simplest solution is to use a Promise library.

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

In a sequential way (exemple with Bluebird) :

以顺序方式(例如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
});

If sequential requests aren't needed (here an example with Q) :

如果不需要顺序请求(这里是Q的示例):

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

回答by mscdex

You could use the asyncmodule to easily handle those kinds of async tasks.

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

Specifically async.eachor async.eachLimitif you need concurrency > 1 or async.eachSeriesif you want to go through the items in the array, one at a time.

特别是async.eachasync.eachLimit如果您需要并发 > 1 或async.eachSeries如果您想遍历数组中的项目,一次一个。

回答by Katya S

I have to admit I haven't managed to get Denys Séguret's solution working (for the async calls within .each() loop) - the "after" operation still happens before the .each() loop is completed, however I found a different way, and I hope it helps someone:

我不得不承认我还没有设法让 Denys Sé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
        }
    });
});

In this particular code example it looks like you could be doing your async calls within then mapping functions, but you get the gist...

在这个特定的代码示例中,您似乎可以在 then 映射函数中进行异步调用,但是您明白了要点……

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

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

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

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