摘要:今天碰到一個(gè)需要用做無窮循環(huán)的一個(gè)案例,頓時(shí)腦洞大開。事情是這樣的,有這樣的一群異步函數(shù),將它們封裝成,依次放入一個(gè)數(shù)組內(nèi)需要讓數(shù)組里的每一個(gè)依次進(jìn)行,最后一個(gè)執(zhí)行完就結(jié)束。
今天碰到一個(gè)需要用Promise做無窮循環(huán)then的一個(gè)案例,頓時(shí)腦洞大開。
事情是這樣的,有這樣的一群異步函數(shù),
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,依次放入一個(gè)數(shù)組內(nèi):
// 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)];
需要讓數(shù)組里的每一個(gè)Promise依次進(jìn)行,最后一個(gè)執(zhí)行完就結(jié)束。
我的第一個(gè)想法是這樣的:
// 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]();
乍看沒有問題啊,每一個(gè)新的master子函數(shù)的值是它上一個(gè)子函數(shù)的值加上一個(gè)then,但是一直報(bào)錯(cuò)——Maximum call stack size exceeded (node) / too much recursion (firefox)。
(12/24圣誕夜更新:已解決,修改了部分代碼見下文)
僵了一會(huì),還是谷哥幫助了我,搜到一個(gè)非常簡潔的方法:
// solution 2 // success func_arr.reduce(function(cur, next) { return cur.then(next); }, Promise.resolve()).then(function() { console.log("job finished"); });
看得我腿都拍出坑了,其實(shí)是我想復(fù)雜了,沒有必要在循環(huán)里不斷地返回閉包函數(shù)等到最后調(diào)用,可以直接在循環(huán)里調(diào)用。
于是心有不甘,reduce()能實(shí)現(xiàn)的我大for豈有實(shí)現(xiàn)不了的道理,實(shí)則也不難,正確方法如下:
// 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]); };
以下再提供一種重復(fù)調(diào)用函數(shù)式(就是遞歸)的方法:
// 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"); });
不知道大家還有沒有更好的解決方案,或者能告知我第一個(gè)方案出錯(cuò)的原因吧
================
12/24更新感謝wowhy的提示,將我的solution 1的代碼加入一層閉包,已經(jīng)解決了因內(nèi)外函數(shù)變量產(chǎn)生的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();
乍看這一串代碼很長,對(duì)比之前的方案顯得完全多余,在我看來,可以生成在外部其他的上下文內(nèi)進(jìn)行獨(dú)立調(diào)用的函數(shù)要更符合我大腦的思維方式:)。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/78354.html
摘要:在將來的其他規(guī)范中可能會(huì)涉及這些沒有提及的內(nèi)容。它禁止被觸發(fā)多次。如果到了狀態(tài),那么所有的回調(diào)函數(shù)都必須按照他們?cè)械捻樞蜻M(jìn)行調(diào)用執(zhí)行。 概述 自從準(zhǔn)備晉級(jí)之后,就拖更了很久了,既然晉級(jí)弄完了,那么也恢復(fù)更新了。 在面試別人的過程中,發(fā)現(xiàn)基本上沒有人對(duì)整個(gè)Promise完全了解,因此希望通過這篇文章來幫助大家了解下Promise的全貌。本文的主要內(nèi)容是Promise/A+規(guī)范的譯文,主...
摘要:執(zhí)行權(quán)由此單向穩(wěn)定的在不同函數(shù)中切換。調(diào)用函數(shù)后,引擎會(huì)為其開辟一個(gè)獨(dú)立的函數(shù)執(zhí)行棧以下簡稱棧。執(zhí)行權(quán)再次回到外部。成功執(zhí)行完函數(shù),則改變的狀態(tài)為成功。執(zhí)行函數(shù)返回的遍歷器對(duì)象會(huì)繼承函數(shù)的原型對(duì)象。遇到下一個(gè)斷點(diǎn),交出執(zhí)行權(quán)傳出返回值。 前言 ES6提供了一種新型的異步編程解決方案:Generator函數(shù)(以下簡稱G函數(shù))。它不是使用JS現(xiàn)有能力按照一定標(biāo)準(zhǔn)制定出來的東西(Promis...
摘要:接下來我們看下三類異步編程的實(shí)現(xiàn)。事件監(jiān)聽事件發(fā)布訂閱事件監(jiān)聽是一種非常常見的異步編程模式,它是一種典型的邏輯分離方式,對(duì)代碼解耦很有用處。 一、 一道面試題 前段時(shí)間面試,考察比較多的是js異步編程方面的相關(guān)知識(shí)點(diǎn),如今,正好輪到自己分享技術(shù),所以想把js異步編程學(xué)習(xí)下,做個(gè)總結(jié)。下面這個(gè)demo 概括了大多數(shù)面試過程中遇到的問題: for(var i = 0; i < 3; i++...
摘要:縮進(jìn)為個(gè)空格句末必須用分號(hào)結(jié)尾待定就無分號(hào)注釋單行注釋多行注釋代碼注釋和再提交重要函數(shù)或者類等都要添加頭描述字符串拼接應(yīng)使用數(shù)組保存字符串片段,使用時(shí)調(diào)用方法。 前言 下面這幾點(diǎn)將工作中所踩的一些坑簡單整理了一下,團(tuán)隊(duì)幾個(gè)人開發(fā),一些默契就比較重要,可以提高開發(fā)效率和代碼的可讀性 命名,編碼和注釋 命名 A.文件夾命名:文件夾、文件的命名與命名空間應(yīng)能代表代碼功能,可讀性強(qiáng),如hubB...
摘要:前言轉(zhuǎn)簡體重新排版布局代碼全面使用并且直接附上輸出結(jié)果補(bǔ)充細(xì)節(jié)補(bǔ)充內(nèi)容增加例子說明新增和在遍歷情況下怎么使用上文講了關(guān)于執(zhí)行機(jī)制單線程同異步任務(wù)事件循環(huán)的知識(shí)點(diǎn)我們知道在某一時(shí)刻內(nèi)只能執(zhí)行特定的一個(gè)任務(wù)并且會(huì)阻塞其它任務(wù)執(zhí)行為了解決這個(gè) 前言 PS:2018/08/08 轉(zhuǎn)簡體2018/08/09 重新排版布局,代碼全面使用ES6并且直接附上輸出結(jié)果,補(bǔ)充細(xì)節(jié)2018/08/13 補(bǔ)充...
閱讀 1058·2021-11-18 10:02
閱讀 1314·2021-09-23 11:22
閱讀 2617·2021-08-21 14:08
閱讀 1643·2019-08-30 15:55
閱讀 1729·2019-08-30 13:45
閱讀 3169·2019-08-29 16:52
閱讀 3100·2019-08-29 12:18
閱讀 1644·2019-08-26 13:36