forEach里面的异步函数用js循环

Jef*_*nte 6 javascript

可能重复:
javascript:使用一个回调执行一堆异步方法

我几天来一直在努力解决这个问题,但我无法想出一个优雅的方法来处理它.这是问题所在.

我正在运行forEach循环,我需要知道什么时候一切都已完成.由于forEach循环是阻塞的,因此只需console.log在forEach循环之后删除a 就足够了,这将在forEach循环完成时运行.但是,如果forEach循环内部有任何不同步的函数,整个系统会很快崩溃,除了非常奇怪的hacky计数器和if语句之外,我无法知道循环内容何时完成.我的问题是在javascript中是否有一种优雅的方式来处理这种情况.

以下是几个例子:

在这种情况下,forEach循环可以很好地工作,因为循环中的所有内容都是同步的.

[1,2,3].forEach(function(num){
  console.log("we're on " + num);
});
console.log('done counting!')

//=> we're on 1
//=> we're on 2
//=> we're on 3
//=> done counting!
Run Code Online (Sandbox Code Playgroud)

这是我们开始遇到问题的地方,作为一个基本的例子:

[1,2,3].forEach(function(num){
  setTimeout(function(){ console.log(num) }, 200);
});
console.log('done counting!');

//=> done counting!
//=> we're on 1
//=> we're on 2
//=> we're on 3
Run Code Online (Sandbox Code Playgroud)

虽然这确实发生了这种情况,但我现在手上有一个不幸的问题,我需要回调一下,当我们完成计数时,除了这样的事情之外我没有其他方法可以做到:

var counter = 0;
var numbers = [1,2,3]

var log_number = function(num){
  console.log("we're on " + num);
  counter++;
  if (counter == numbers.length) {
    console.log("done counting!")
  }
}

numbers.forEach(function(num){
  setTimeout(log_number(num), 200);
});

//=> we're on 1
//=> we're on 2
//=> we're on 3
//=> done counting!
Run Code Online (Sandbox Code Playgroud)

善良,这是一个非常大的开销.有没有更顺畅的方法来实现这一目标?我已经检查了promises,deferred和sequence,但是我还没有真正能够以更简洁的方式实现其中任何一个:(

要清楚,它不是setTimeout特别是我的问题,它通常在同步函数内运行异步函数 - 这只是最简单的例子.

zer*_*osh 7

Array.prototype.forEachDone = function(fn, scope, lastfn) {
    for(var i = 0, c = 0, len = this.length; i < len; i++) {
        fn.call(scope, this[i], i, this, function() {
            ++c === len && lastfn();
        });
    }
};

[1,2,3].forEachDone(function(num, i, arr, done){
  setTimeout(function(){ console.log(num); done() }, 200);
}, this, function() {
    console.log('done counting!');
});
Run Code Online (Sandbox Code Playgroud)

这将做你想要的.forEachDone将采用与forEach完全相同的参数,最后一个参数是在应用于数组的每个元素的函数完成时调用的回调.将应用于数组中每个元素的函数也采用与forEach完全相同的参数,但也使用另一个函数,该函数应在函数完成时调用.

PS:就个人而言,我永远不会触及本机对象的原型,但如果你正在寻找漂亮,那就是它.


小智 -1

[1,2,3,4,5,6,7,8].forEach(function(n){
 setTimeout(function(){
  console.log(arguments[0]);
 },1000*n,n);
});
Run Code Online (Sandbox Code Playgroud)

这对我来说很好用