Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
455 views
in Technique[技术] by (71.8m points)

javascript - 所有异步forEach回调完成后的回调(Callback after all asynchronous forEach callbacks are completed)

As the title suggests.

(如标题所示。)

How do I do this?

(我该怎么做呢?)

I want to call whenAllDone() after the forEach-loop has gone through each element and done some asynchronous processing.

(我想在forEach循环遍历每个元素并进行一些异步处理后调用whenAllDone() 。)

[1, 2, 3].forEach(
  function(item, index, array, done) {
     asyncFunction(item, function itemDone() {
       console.log(item + " done");
       done();
     });
  }, function allDone() {
     console.log("All done");
     whenAllDone();
  }
);

Possible to get it to work like this?

(有可能让它像这样工作吗?)

When the second argument to forEach is a callback function which runs once it went through all iterations?

(当forEach的第二个参数是一个回调函数,该函数一旦经过所有迭代便会运行?)

Expected output:

(预期产量:)

3 done
1 done
2 done
All done!
  ask by Dan Andreasson translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Array.forEach does not provide this nicety (oh if it would) but there are several ways to accomplish what you want:

(Array.forEach不提供这种功能(哦,如果可以的话),但是有几种方法可以实现您想要的功能:)

Using a simple counter(使用一个简单的计数器)

function callback () { console.log('all done'); }

var itemsProcessed = 0;

[1, 2, 3].forEach((item, index, array) => {
  asyncFunction(item, () => {
    itemsProcessed++;
    if(itemsProcessed === array.length) {
      callback();
    }
  });
});

(thanks to @vanuan and others) This approach guarantees that all items are processed before invoking the "done" callback.

((由于@vanuan等),这种方法可确保在调用“完成”回调之前处理所有项目。)

You need to use a counter that gets updated in the callback.

(您需要使用在回调中更新的计数器。)

Depending on the value of the index parameter does not provide the same guarantee, because the order of return of the asynchronous operations is not guaranteed.

(依赖于index参数的值不能提供相同的保证,因为不能保证异步操作的返回顺序。)

Using ES6 Promises(使用ES6承诺)

(a promise library can be used for older browsers):

((承诺库可用于较旧的浏览器):)

  1. Process all requests guaranteeing synchronous execution (eg 1 then 2 then 3)

    (处理所有保证同步执行的请求(例如1到2然后3))

     function asyncFunction (item, cb) { setTimeout(() => { console.log('done with', item); cb(); }, 100); } let requests = [1, 2, 3].reduce((promiseChain, item) => { return promiseChain.then(() => new Promise((resolve) => { asyncFunction(item, resolve); })); }, Promise.resolve()); requests.then(() => console.log('done')) 
  2. Process all async requests without "synchronous" execution (2 may finish faster than 1)

    (处理所有异步请求而无需“同步”执行(2个可能比1个完成得快))

     let requests = [1,2,3].map((item) => { return new Promise((resolve) => { asyncFunction(item, resolve); }); }) Promise.all(requests).then(() => console.log('done')); 

Using an async library(使用异步库)

There are other asynchronous libraries, async being the most popular, that provide mechanisms to express what you want.

(还有其他异步库( 异步是最流行的),它们提供了表达所需内容的机制。)

Edit

(编辑)


The body of the question has been edited to remove the previously synchronous example code, so i've updated my answer to clarify.

(对问题的正文进行了编辑,以删除先前同步的示例代码,因此我更新了答案以进行澄清。)

The original example used synchronous like code to model asynchronous behaviour, so the following applied:

(原始示例使用类似同步的代码来建模异步行为,因此适用以下内容:)

array.forEach is synchronous and so is res.write , so you can simply put your callback after your call to foreach:

(array.forEach同步的 ,所以是res.write ,所以你可以简单地把你的回调您的来电后的foreach:)

  posts.foreach(function(v, i) { res.write(v + ". index " + i); }); res.end(); 

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...