javascript 中 while 循环异步的正确方法

proper way to do while loop async in javascript

我想知道这样做的正确方法是什么?

while(newList.length < 10){
            async.series([
                function(callback){         
                    async.eachSeries(rest,function(id,next){
                        if(getDistance(myLoc,id) < 5){
                            newList.push(id);
                        }
                        next();
                    });
                    callback();
                },
                function(callback){
                    var size = 10 - newList.length
                    rest = getPlaces()
                    callback();
                }], function(err,results){
                    if(err) console.log('error occured in : ' + err);
                });
        }

rest 每隔 运行 填充 10 个新位置,而 asyc 过程的第一步是找出这 10 个位置的距离是否在 5km 以内,如果在 5km 以内,则为添加到newList,如果没有再循环,直到找到10个距离在5km以内的地方

虽然真正的想法是重新迭代,直到我的 newList 充满 10 个(距离 < 10 公里的地方),当我尝试 运行 这个时,它只遍历了所有内容并成功了' t 循环第二个 运行.

我的建议是在 while 范围之外设置一个布尔变量,默认情况下为 true,当 async 函数用 10 个元素填充列表时将其设置为 false。希望对您有所帮助。

使用异步 while 而不是常规 while:

var newList = [];
async.whilst(
    function(){ return newList.length < 10;},
    function(done) {
        async.series([
           function(callback){  
               var size = 10 - newList.length
               rest = getPlaces()
               callback();       
           },
           function(callback){
               async.eachSeries(rest,function(id,next){
                   if(getDistance(myLoc,id) < 5){
                        newList.push(id);
                   }
                   next();
               });
               callback();
           }], 
           function(err,results){
               if(err) console.log('error occured in : ' + err);
               done(err, newList);
           };    
    },
    function(results) {
        // New list has been filled
    }
})

好的,所以你这里有几个问题。
让我们从这个开始:

function(callback){         
    async.eachSeries(rest,function(id,next){
        if(getDistance(myLoc,id) < 5){
            newList.push(id);
        }
        next();
    });
    callback();
}

您不是在等待 eachSeries 的输出,而是在启动它,然后立即回调。
该功能将独立地填写您的newList,可能会立即,可能会稍有延迟;你不会知道的,因为你马上回电了。
您在这里使用 series 也不会获得任何好处,因为它应该在前一个功能完成后 运行 每个功能。
您的代码最终可能会像这样工作:

  • 开始async.series
  • 运行第一个函数
  • 函数开始 async.eachSeries
  • 函数回调
  • 第二个功能开始,newList还没有填充
  • 第二个功能结束
  • 循环结束
  • newList未填写

除此之外,您的 while 函数也不必等待任何事情,它会无意识地 运行 async.series 一遍又一遍,直到您的 newList 被填满,很可能会占用大量资源。 您可以改用 async.whilst 之类的函数,例如:

async.whilst(
    function() { return newList.length < 10; },
    function(callback) {
        ...
    }, function(err, results) {
        console.log('loop has ended')
    }
)

此外,您可能应该使用 series 的回调来生成结果数组,并在循环结束时处理它们,而不是让函数随机且不可预测地填充内容。
例如:

function(callback){
    var list = []
    async.eachSeries(rest,function(id,next){
        if(getDistance(myLoc,id) < 5){
            list.push(id);
        }
        next();
    }, function(err) {
        callback(err, list);
    });
}

我希望这对您的问题有所帮助。