摘要:今天碰到一個需要用做無窮循環的一個案例,頓時腦洞大開。事情是這樣的,有這樣的一群異步函數,將它們封裝成,依次放入一個數組內需要讓數組里的每一個依次進行,最后一個執行完就結束。
今天碰到一個需要用Promise做無窮循環then的一個案例,頓時腦洞大開。
事情是這樣的,有這樣的一群異步函數,
var func1 = function(callback){ setTimeout(function(){ console.log("foo"); typeof(callback) !== "function" || callback(); }, 499); }; var func2 = function(callback){ setTimeout(function(){ console.log("bar"); typeof(callback) !== "function" || callback(); }, 500); }; var func3 = function(callback){ setTimeout(function(){ console.log("foobar"); typeof(callback) !== "function" || callback(); }, 501); }; // ... more ...
將它們封裝成Promise,依次放入一個數組內:
// promisify those callback functions var promisify = function(func){ return function(){ return new Promise(function(resolve){ func(resolve); }); } } // array can be infinitely long var func_arr = [promisify(func1), promisify(func2), promisify(func3)];
需要讓數組里的每一個Promise依次進行,最后一個執行完就結束。
我的第一個想法是這樣的:
// solution 1 failed var master = []; for (var i = 0; i < func_arr.length; i++) { master[i] = function(){ if (i == 0) { return func_arr[i](); } else { return master[i-1]().then(function(){ return func_arr[i](); }) } }; }; master[master.length-1]();
乍看沒有問題啊,每一個新的master子函數的值是它上一個子函數的值加上一個then,但是一直報錯——Maximum call stack size exceeded (node) / too much recursion (firefox)。
(12/24圣誕夜更新:已解決,修改了部分代碼見下文)
僵了一會,還是谷哥幫助了我,搜到一個非常簡潔的方法:
// solution 2 // success func_arr.reduce(function(cur, next) { return cur.then(next); }, Promise.resolve()).then(function() { console.log("job finished"); });
看得我腿都拍出坑了,其實是我想復雜了,沒有必要在循環里不斷地返回閉包函數等到最后調用,可以直接在循環里調用。
于是心有不甘,reduce()能實現的我大for豈有實現不了的道理,實則也不難,正確方法如下:
// solution 3 // success var master = []; master[0] = func_arr[0](); for (var i = 1; i < func_arr.length; i++) { master[i] = master[i-1].then(func_arr[i]); };
以下再提供一種重復調用函數式(就是遞歸)的方法:
// solution 4 // success function loop(i) { if (i != func_arr.length) { return func_arr[i]() .then(function() { return loop(i+1); }); } return Promise.resolve(i); } loop(0).then(function(loop_times){ console.log("job finished"); });
不知道大家還有沒有更好的解決方案,或者能告知我第一個方案出錯的原因吧
================
12/24更新感謝wowhy的提示,將我的solution 1的代碼加入一層閉包,已經解決了因內外函數變量產生的BUG:
// solution 1 // success now var master = []; for (var i = 0; i < func_arr.length; i++) { master[i] = (function(j){ return function(){ if (j == 0) { return func_arr[j](); } else { return master[j-1]().then(function(){ return func_arr[j](); }) } } })(i); }; var execute = master[master.length-1]; execute();
乍看這一串代碼很長,對比之前的方案顯得完全多余,在我看來,可以生成在外部其他的上下文內進行獨立調用的函數要更符合我大腦的思維方式:)。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/78354.html
摘要:在將來的其他規范中可能會涉及這些沒有提及的內容。它禁止被觸發多次。如果到了狀態,那么所有的回調函數都必須按照他們原有的順序進行調用執行。 概述 自從準備晉級之后,就拖更了很久了,既然晉級弄完了,那么也恢復更新了。 在面試別人的過程中,發現基本上沒有人對整個Promise完全了解,因此希望通過這篇文章來幫助大家了解下Promise的全貌。本文的主要內容是Promise/A+規范的譯文,主...
摘要:執行權由此單向穩定的在不同函數中切換。調用函數后,引擎會為其開辟一個獨立的函數執行棧以下簡稱棧。執行權再次回到外部。成功執行完函數,則改變的狀態為成功。執行函數返回的遍歷器對象會繼承函數的原型對象。遇到下一個斷點,交出執行權傳出返回值。 前言 ES6提供了一種新型的異步編程解決方案:Generator函數(以下簡稱G函數)。它不是使用JS現有能力按照一定標準制定出來的東西(Promis...
摘要:接下來我們看下三類異步編程的實現。事件監聽事件發布訂閱事件監聽是一種非常常見的異步編程模式,它是一種典型的邏輯分離方式,對代碼解耦很有用處。 一、 一道面試題 前段時間面試,考察比較多的是js異步編程方面的相關知識點,如今,正好輪到自己分享技術,所以想把js異步編程學習下,做個總結。下面這個demo 概括了大多數面試過程中遇到的問題: for(var i = 0; i < 3; i++...
摘要:前言轉簡體重新排版布局代碼全面使用并且直接附上輸出結果補充細節補充內容增加例子說明新增和在遍歷情況下怎么使用上文講了關于執行機制單線程同異步任務事件循環的知識點我們知道在某一時刻內只能執行特定的一個任務并且會阻塞其它任務執行為了解決這個 前言 PS:2018/08/08 轉簡體2018/08/09 重新排版布局,代碼全面使用ES6并且直接附上輸出結果,補充細節2018/08/13 補充...
閱讀 1049·2021-11-18 10:02
閱讀 1304·2021-09-23 11:22
閱讀 2607·2021-08-21 14:08
閱讀 1636·2019-08-30 15:55
閱讀 1720·2019-08-30 13:45
閱讀 3141·2019-08-29 16:52
閱讀 3092·2019-08-29 12:18
閱讀 1636·2019-08-26 13:36