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