摘要:今天我們接著上次的內(nèi)容繼續(xù)扯,如何實(shí)現(xiàn)數(shù)據(jù)傳遞以及當(dāng)回調(diào)函數(shù)返回一個(gè)新的上篇已完成的代碼測(cè)試代碼上面的結(jié)果,就是我們要實(shí)現(xiàn)的。然后,等到下次需要的時(shí)候,再傳給下一個(gè)回調(diào)函數(shù)。先來(lái)修改方法,因?yàn)榛卣{(diào)函數(shù)都是在這里運(yùn)行的。
上一篇文章【實(shí)現(xiàn)簡(jiǎn)易 ES6 Promise 功能 (一)】實(shí)現(xiàn)了基本的異步功能。今天我們接著上次的內(nèi)容繼續(xù)扯,如何實(shí)現(xiàn)【數(shù)據(jù)傳遞】以及當(dāng)【回調(diào)函數(shù)返回一個(gè)新的promise】
上篇已完成的代碼
function Promise(func){ this.state = "pending"; this.doneList = []; func(this.resolve.bind(this)); } Promise.prototype = { resolve: function(){ while(true){ if( this.doneList.length === 0 ){ this.state = "done"; break; } this.doneList.shift().apply(this); } }, then: function(callback){ this.doneList.push(callback); if( this.state === "done"){ this.state = "pending"; this.resolve(); } return this; } }
測(cè)試代碼
new Promise(function(resolve){ resolve(1) }).then(function(data){ console.log(data); // 1 return 2; }).then(function(data){ console.log(data); // 2 });
上面的結(jié)果,就是我們要實(shí)現(xiàn)的。resolve的參數(shù)(只傳遞第一個(gè)參數(shù),如果有)傳遞給第一個(gè)then里面函數(shù)作為參數(shù),第一個(gè)then里面的函數(shù)返回值傳遞給第二個(gè)then里面的函數(shù)作為參數(shù),以此類推。
關(guān)鍵代碼
resolve: function(){ // arguments[0]是resolve的第一個(gè)參數(shù) while(true){ if( this.doneList.length === 0 ){ this.state = "done"; break; } // 這里是運(yùn)行then里面回調(diào)函數(shù)的地方 this.doneList.shift().apply(this); } }
如何修改呢?除了第一次傳遞參數(shù),是把resolve的參數(shù)往下傳遞,其余的都是把上次的結(jié)果作為下次開(kāi)始(參數(shù))。
于是,我們可以先把上次doneList里面的函數(shù)運(yùn)行結(jié)果保存起來(lái)。然后,等到下次需要的時(shí)候,再傳給下一個(gè)回調(diào)函數(shù)。
代碼修改:
resolve: function(){ // arguments[0]是resolve的第一個(gè)參數(shù) var arg = arguments[0]; while(true){ if( this.doneList.length === 0 ){ this.state = "done"; break; } // 這里是運(yùn)行then里面回調(diào)函數(shù)的地方 // 以數(shù)組形式傳給下一個(gè)函數(shù),然后保存新的值 // 判斷傳遞的參數(shù)是否為undefined,是的話,就不用傳了 if( typeof arg === "undefined" ){ arg = this.doneList.shift().apply(this); }else{ arg = this.doneList.shift().apply(this, [arg]); } } // 保存最后的arg,保證后續(xù)的回調(diào)能繼續(xù)得到參數(shù) this.arg = arg; } // 還需要修改then方法 then: function(callback){ this.doneList.push(callback); if( this.state === "done"){ this.state = "pending"; this.resolve(this.arg); // 注意這里也要傳遞參數(shù) } return this; }
第一次修改完善的代碼,及測(cè)試結(jié)果
function Promise(func){ this.state = "pending"; this.doneList = []; func(this.resolve.bind(this)); } Promise.prototype = { resolve: function(){ // arguments[0]是resolve的第一個(gè)參數(shù) var arg = arguments[0]; while(true){ if( this.doneList.length === 0 ){ this.state = "done"; break; } // 這里是運(yùn)行then里面回調(diào)函數(shù)的地方 // 以數(shù)組形式傳給下一個(gè)函數(shù),然后保存新的值 // 判斷傳遞的參數(shù)是否為undefined,是的話,就不用傳了 if( typeof arg === "undefined" ){ arg = this.doneList.shift().apply(this); }else{ arg = this.doneList.shift().apply(this, [arg]); } } // 保存最后的arg,保證后續(xù)的回調(diào)能繼續(xù)得到參數(shù) this.arg = arg; }, then: function(callback){ this.doneList.push(callback); if( this.state === "done"){ this.state = "pending"; this.resolve(this.arg); // 注意這里也要傳遞參數(shù) } return this; } } // 測(cè)試 new Promise(function(resolve){ resolve(1) }).then(function(data){ console.log(data); // 1 return 2; }).then(function(data){ console.log(data); // 2 });
結(jié)果截圖:
今天的第一個(gè)功能已經(jīng)完了,那么現(xiàn)在開(kāi)始開(kāi)發(fā)第二個(gè)功能。
先看一個(gè)測(cè)試
new Promise(function(resolve){ resolve(1) }).then(function(data){ console.log(data, 2); // 1,2 return new Promise(function(resolve){ window.setTimeout(function(){ resolve(3); }, 1000); }).then(function(data){ console.log(data, 4); // 3,4 return 5; }); }).then(function(data){ console.log(data, 6); // 5, 6 });
測(cè)試結(jié)果
我在上面測(cè)試?yán)又校瑃hen回調(diào)函數(shù)中返回的promise中故意使用了延遲函數(shù)。但是,輸出結(jié)果中5往后傳了,并且[5,6]是在[3,4]之后,且都有一秒中的延遲。
如果沒(méi)有回調(diào)返回一個(gè)promise,程序會(huì)一直按照第一行走下去,就算回調(diào)中有其他promise(只要不return),也是兩條并行的線。一旦返回promise,新的promise會(huì)在這個(gè)點(diǎn)插入,并且原來(lái)還沒(méi)有執(zhí)行的回調(diào),也會(huì)排到新的回調(diào)列表后面了。
先來(lái)修改resolve方法,因?yàn)榛卣{(diào)函數(shù)都是在這里運(yùn)行的。
resolve: function(){ // arguments[0]是resolve的第一個(gè)參數(shù) var arg = arguments[0]; while(true){ if( this.doneList.length === 0 ){ this.state = "done"; break; } /*************************/ if( arg instanceof Promise ){ // 把新的promise保存起來(lái),待會(huì)要用 this.promise = arg; // 本promise沒(méi)有執(zhí)行完的回調(diào)全部加入到新的回調(diào)列表 arg.doneList = arg.doneList.concat(this.doneList); // 改變回調(diào)及狀態(tài) this.doneList.length = 0; this.state = "done"; // 跳出循環(huán) break; } /*************************/ // 這里是運(yùn)行then里面回調(diào)函數(shù)的地方 // 以數(shù)組形式傳給下一個(gè)函數(shù),然后保存新的值 // 判斷傳遞的參數(shù)是否為undefined,是的話,就不用傳了 if( typeof arg === "undefined" ){ arg = this.doneList.shift().apply(this); }else{ arg = this.doneList.shift().apply(this, [arg]); } } // 保存最后的arg,保證后續(xù)的回調(diào)能繼續(xù)得到參數(shù) this.arg = arg; } then: function(callback){ this.doneList.push(callback); if( this.state === "done"){ this.state = "pending"; this.resolve(this.arg); // 注意這里也要傳遞參數(shù) } // 這里不能在返回this了,而是一個(gè)promise對(duì)象 return this.promise; } // 如果then沒(méi)有返回promise,那么this.promise = this; function Promise(func){ this.state = "pending"; this.doneList = []; func(this.resolve.bind(this)); // 默認(rèn)指向本身 this.promise = this; }
本期完整代碼
function Promise(func){ this.state = "pending"; this.doneList = []; func(this.resolve.bind(this)); this.promise = this; } Promise.prototype = { resolve: function(){ // arguments[0]是resolve的第一個(gè)參數(shù) var arg = arguments[0]; while(true){ if( this.doneList.length === 0 ){ this.state = "done"; break; } if( arg instanceof Promise ){ this.promise = arg; arg.doneList = arg.doneList.concat(this.doneList); this.doneList.length = 0; this.state = "done"; break; } // 這里是運(yùn)行then里面回調(diào)函數(shù)的地方 // 以數(shù)組形式傳給下一個(gè)函數(shù),然后保存新的值 // 判斷傳遞的參數(shù)是否為undefined,是的話,就不用傳了 if( typeof arg === "undefined" ){ arg = this.doneList.shift().apply(this); }else{ arg = this.doneList.shift().apply(this, [arg]); } } // 保存最后的arg,保證后續(xù)的回調(diào)能繼續(xù)得到參數(shù) this.arg = arg; }, then: function(callback){ this.doneList.push(callback); if( this.state === "done"){ this.state = "pending"; this.resolve(this.arg); // 注意這里也要傳遞參數(shù) } return this.promise; } }
結(jié)束。謝謝大家閱讀,如有錯(cuò)誤或建議請(qǐng)給我留言或者發(fā)私信。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/78565.html
摘要:對(duì)象用于延遲計(jì)算和異步計(jì)算。一個(gè)對(duì)象代表著一個(gè)還未完成,但預(yù)期將來(lái)會(huì)完成的操作。接收一個(gè)函數(shù)作為參數(shù)接收函數(shù)作為參數(shù)支持鏈?zhǔn)秸{(diào)用是按照順序來(lái)執(zhí)行的,并且由觸發(fā)。下篇繼續(xù)完善,例如數(shù)據(jù)傳遞以及中函數(shù)返回一個(gè)時(shí),如何處理。 Promise 對(duì)象用于延遲(deferred) 計(jì)算和異步(asynchronous ) 計(jì)算。一個(gè)Promise對(duì)象代表著一個(gè)還未完成,但預(yù)期將來(lái)會(huì)完成的操作。 先...
前言 作為一個(gè)后端過(guò)來(lái)的同學(xué),剛?cè)腴T前端的時(shí)候,被js種種「反人類」的概念折騰的死去活來(lái)的.其中一個(gè)印象比較深刻的,就是promise,感覺(jué)實(shí)在太難理解了...所有就有了寫個(gè)簡(jiǎn)單的promise的想法.希望能幫助到一些跟我一樣,感覺(jué)promise很難理解的新同學(xué). promise的教程網(wǎng)上多如牛毛,其中寫的比較通俗易懂的莫過(guò)于阮一峰的es6,反正我是他的書才懂的.所以今天,我們也不會(huì)來(lái)復(fù)述一遍如何...
摘要:在處理異步回調(diào)函數(shù)的情況有著越來(lái)越值得推崇的方法及類庫(kù),下面會(huì)依次介紹處理異步函數(shù)的發(fā)展史,及源碼解讀。而對(duì)象的狀態(tài),是由第一個(gè)的參數(shù)成功回調(diào)函數(shù)或失敗回調(diào)函數(shù)的返回值決定的。 函數(shù)的執(zhí)行分為同步和異步兩種。同步即為 同步連續(xù)執(zhí)行,通俗點(diǎn)講就是做完一件事,再去做另一件事。異步即為 先做一件事,中間可以去做其他事情,稍后再回來(lái)做第一件事情。同時(shí)還要記住兩個(gè)特性:1.異步函數(shù)是沒(méi)有返回值的...
摘要:錯(cuò)過(guò)了一周的優(yōu)質(zhì)內(nèi)容,不要再錯(cuò)過(guò)周一的快速回顧一周深度揭秘啟動(dòng)全過(guò)程翻譯組每周社區(qū)問(wèn)答入門語(yǔ)言簡(jiǎn)明入門與提高一只爬蟲崔小拽爬蟲知乎用戶數(shù)據(jù)爬取和分析如何學(xué)習(xí)開(kāi)源動(dòng)效分析二動(dòng)畫最佳實(shí)踐一工具箱之生命周期工具箱之權(quán)限管理一步步創(chuàng)建自己的框 錯(cuò)過(guò)了一周的優(yōu)質(zhì)內(nèi)容,不要再錯(cuò)過(guò)周一的快速回顧 一周 fir.im Weekly -《深度揭秘 App 啟動(dòng)全過(guò)程》 SwiftGG翻譯組 -《每周 S...
摘要:錯(cuò)過(guò)了一周的優(yōu)質(zhì)內(nèi)容,不要再錯(cuò)過(guò)周一的快速回顧一周深度揭秘啟動(dòng)全過(guò)程翻譯組每周社區(qū)問(wèn)答入門語(yǔ)言簡(jiǎn)明入門與提高一只爬蟲崔小拽爬蟲知乎用戶數(shù)據(jù)爬取和分析如何學(xué)習(xí)開(kāi)源動(dòng)效分析二動(dòng)畫最佳實(shí)踐一工具箱之生命周期工具箱之權(quán)限管理一步步創(chuàng)建自己的框 錯(cuò)過(guò)了一周的優(yōu)質(zhì)內(nèi)容,不要再錯(cuò)過(guò)周一的快速回顧 一周 fir.im Weekly -《深度揭秘 App 啟動(dòng)全過(guò)程》 SwiftGG翻譯組 -《每周 S...
閱讀 2856·2021-11-23 09:51
閱讀 2476·2021-09-30 09:48
閱讀 2124·2021-09-22 15:24
閱讀 1079·2021-09-06 15:02
閱讀 3437·2021-08-17 10:14
閱讀 2009·2021-07-30 18:50
閱讀 2038·2019-08-30 15:53
閱讀 3259·2019-08-29 18:43