2016-11-23 47 views
0

我正在使用Array.forEach函數javascript來獲取列表中的每個元素的不同消息。所以我使用forEach函數,並且我正在尋找一個way來執行我的callback函數cb(result),當foreach完成時同時執行.forEachmsgAfterTimeout。我讀到有一種叫做promises的東西,但我真的不明白我在這裏如何使用它們。Array.forEach回調在最後

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); 
}); 
+0

結果應該包含什麼?它在上面沒有定義。 – Joe

回答

0

這裏是與承諾的例子:

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')) 
 
);

參考:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

+0

正是我在尋找的感謝 – Yokida

0
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!"); 
}); 

此輸出:

你好富! 你好吉恩! 完成所有!

0

forEach系列處理的事情,所以對於這個答案的緣故,讓我們假設這是一個要求。 Promise.all由@georg演示將處理平行中的項目 - 這是一個很好的答案,但它不會幫助你,如果一系列是你真正需要的。

Array.prototype方法reduce,mapforEach是同步的,但您可以輕鬆地創建一個異步變體。您在這裏使用forEach,但您實際上正在手動執行reduce。所以我們首先實施異步reducek,然後從那裏開始

不要太在意瞭解reducek本身。所有你需要知道的是reducekreduce之間的主要區別在於還原函數接收到每個項目完成時調用的額外回調參數,並且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!

重要的事情需要注意...

  1. 不再進行手工減少 - 而不是使用test變量與''狀態初始化(空字符串),reducek接受初始值作爲參數。

  2. 這裏我們使用[](空數組)的初始狀態來存儲每個文本。當我們完成後,我們使用texts.join(' ')加入文本。


不是另一種儀式...

所有的這是一個很大的儀式和延續的不一定是最好的異步流量控制。事實上,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!

注意:如果你需要支持舊的瀏覽器,需要async/await使用像巴貝爾被transpiled。