[英]Array.forEach Callback at the end
I'm using Array.forEach
function of javascript to get a different message for each element of a list. 我正在使用javascript的
Array.forEach
函数为列表的每个元素获取不同的消息。 So I'm using forEach
function and I'm looking for a way
to execute my callback
function cb(result)
when the foreach as finished to both execute .forEach
and msgAfterTimeout
. 所以我正在使用
forEach
函数,并且正在寻找一种way
来在foreach完成时执行.forEach
和msgAfterTimeout
时执行我的callback
函数cb(result)
。 I read that there was something called promises
but I don't really get how I can use them here. 我读到有些东西叫做
promises
但是我真的不知道如何在这里使用它们。
function msgAfterTimeout (who, timeout, onDone) {
setTimeout(function () {
onDone(" Hello " + who + "!");
}, timeout);
}
var test="";
var list = [{name:"foo",surname:"bar"},{name:"Jean",surname:"dupond"}];
function dispName(cb)
{
list.forEach(function(item, index)
{
msgAfterTimeout(item.name, 200, function (msg)
{
test=msg+"\n";
});
cb(result);
});
}
dispName(function(data){
console.log(data);
});
function msgAfterTimeout (who, timeout, onDone) {
setTimeout(function () {
onDone(" Hello " + who + "!");
}, timeout);
}
var test= "";
var list = [{name:"foo",surname:"bar"},{name:"Jean",surname:"dupond"}];
function newFunc(list, i, endCb) {
var name = list[i].name;
msgAfterTimeout(name, 200, function(msg) {
var test = msg + "\n";
console.log(test);
if(i+1 == list.length) {
endCb();
}
else {
newFunc(list, i+1, endCb);
}
});
}
function dispName(cb)
{
newFunc(list, 0 , cb);
}
dispName(function(){
console.log("Done with all!");
});
This outputs: 输出:
Hello foo!
你好,富! Hello Jean!
你好,简! Done with all!
完成所有!
Here's your example with Promises: 这是您的Promises示例:
var list = [{name: "foo", surname: "bar"}, {name: "Jean", surname: "dupond"}]; function msgAfterTimeout(who, timeout) { return new Promise(resolve => setTimeout( () => resolve(" Hello " + who + "!"), timeout) ); } Promise.all( list.map(item => msgAfterTimeout(item.name, 200)) ).then( result => console.log(result.join('\\n')) );
Reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise 参考: https : //developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise
forEach
processes things in series , so for the sake of this answer, let's assume that's a requirement. forEach
在系列处理的事情,所以对于这个答案起见,我们假设这是一个必要条件。 Promise.all
as demonstrated by @georg will process the items in parallel – it's a good answer but it won't help you if a series is what you actually need. Promise.all
演示的Promise.all将并行处理这些项目–这是一个很好的答案,但是如果您确实需要一系列,它将无法为您提供帮助。
The Array.prototype methods reduce
, map
, and forEach
are synchronous, but you could easily make an asynchronous variants. Array.prototype方法
reduce
, map
和forEach
是同步的,但是您可以轻松地创建异步变量。 You're using forEach
here but you're actually performing a reduce
by hand. 您在这里使用
forEach
,但实际上是在手动执行reduce
。 So we'll start by implementing an asynchronous reducek
and then go from there 因此,我们将从实现异步
reducek
,然后从那里开始
Don't worry too much about understanding reducek
itself. 不必太担心了解
reducek
本身。 All you need to know is the primary difference between reducek
and reduce
is that the reducing function receives an extra callback argument that is called when each item is done, and reducek
has its own callback for when the entire input list is done. 您需要知道的是
reducek
和reduce
之间的主要区别是reducek
函数会收到一个额外的回调参数,该参数在每个项目完成时都会被调用,而reducek
在完成整个输入列表时具有自己的回调。
function reducek (f, acc, [x, ...xs], k) { if (x === undefined) return k (acc) else return f (acc, x, y => reducek (f, y, xs, k)) } function msgAfterTimeout (who, timeout, onDone) { return setTimeout(onDone, timeout, "Hello " + who + "!") } function messageReducer (acc, item, done) { return msgAfterTimeout(item.name, 200, function (text) { return done([...acc, text]) }) } function displayName (list, done) { // use our async reduce here return reducek (messageReducer, [], list, done) } var list = [{name:"foo",surname:"bar"},{name:"Jean",surname:"dupond"}] displayName (list, function (texts) { console.log("Done!", texts.join(' ')) }) // Done! Hello foo! Hello Jean!
Important things to notice ... 重要注意事项...
No longer performing reduce by hand – instead of using a test
variable initialized with state of ''
(empty string), reducek
accepts the initial value as an argument. reducek
不再手动执行reduce –代替使用状态为''
(空字符串)初始化的test
变量, reducek
接受初始值作为参数。
Here we're using an initial state of of []
(empty array) to store each of the texts. 在这里,我们使用初始状态为
[]
(空数组)来存储每个文本。 When we're done, we join the texts together using texts.join(' ')
. 完成后,我们使用
texts.join(' ')
将文本连接在一起。
Not Another Ceremony ... 没有其他仪式...
All of that is a lot of ceremony and continuations are not necessarily the best for asynchronous flow control. 所有这些都是很多仪式,并且延续不一定是异步流控制的最佳方法。 In fact, Promises were brought to JavaScript because a better tool was needed.
实际上,将Promises引入JavaScript的原因是需要更好的工具。
// instead of returning a timeout, return a Promise
function msgAfterTimeout (who, timeout) {
return new Promise(function (resolve) {
setTimeout(resolve, timeout, "Hello " + who + "!")
})
}
// new async/await syntax - work with Promises in a most elegant fashion
// no more callback parameter; async implicitly returns a Promise
async function displayName (list) {
let texts = []
for (let item of list)
texts.push(
await msgAfterTimeout(item.name, 200))
return texts
}
var list = [{name:"foo",surname:"bar"},{name:"Jean",surname:"dupond"}]
// instead of a callback, chain a .then on the returned Promise
displayName(list).then(texts => console.log("Done!", texts.join(' ')))
// Done! Hello foo! Hello Jean!
Note: If you need to support older browsers, async
/ await
needs to be transpiled using something like Babel. 注意:如果您需要支持旧版浏览器,则需要使用Babel这样的东西来对
async
/ await
进行转译。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.