摘要:實(shí)現(xiàn)的一個(gè)簡(jiǎn)單的如果有錯(cuò)誤的地方,希望大家能夠不吝賜教僅實(shí)現(xiàn)及方法最下方有完整代碼開始一個(gè)對(duì)象接收的是一個(gè)這個(gè)接收兩個(gè)參數(shù)當(dāng)我們?cè)趦?nèi)執(zhí)行或的時(shí)候,就會(huì)調(diào)用內(nèi)定義的和函數(shù)然后,和函數(shù)會(huì)改變的狀態(tài)所以它應(yīng)該是像下面這樣的保存值記錄狀態(tài)為,為,為
實(shí)現(xiàn)的一個(gè)簡(jiǎn)單的ES6 Promise(如果有錯(cuò)誤的地方,希望大家能夠不吝賜教)
僅實(shí)現(xiàn)Promise及.then方法開始
最下方有完整代碼
一個(gè)promise對(duì)象接收的是一個(gè)callback
這個(gè)callback接收兩個(gè)參數(shù)(resolve,reject)
當(dāng)我們?cè)?b>callback內(nèi)執(zhí)行resolve或reject的時(shí)候,就會(huì)調(diào)用Promise內(nèi)定義的 resolve和reject函數(shù)
然后,resolve和reject函數(shù)會(huì)改變Promise的狀態(tài)
所以它應(yīng)該是像下面這樣的
function MyPromise(callback) { // 保存this值 var self = this // 記錄狀態(tài)null為pending,true為resolved,false為reject var state = null // 記錄resolve的參數(shù) var param = null // 執(zhí)行傳入的callback并改變promise對(duì)象狀態(tài) callback(resolve, reject) // resolve方法 function resolve(data) { // 改變狀態(tài) state = true param = data } // reject方法 function reject(err) { state = false param = err } }
但沒有then方法的Promise對(duì)象是不完整的(完全沒有用)
所以我們需要一個(gè)then方法,要記住then方法返回的也是一個(gè)promise對(duì)象
then方法接收兩個(gè)可選的參數(shù)(onFulfilled, onRejected)(我們可以先忽略可選兩個(gè)字)
then方法傳進(jìn)來的參數(shù)必須是函數(shù),如果不是就要忽略(PromiseA+規(guī)范)(我們可以也先忽略這句話)
this.then = function (onFulfilled, onRejected) { // 返回一個(gè)新的promise對(duì)象 return new self.constructor(function (resolve, reject) { // then }) }
接下來就是then方法的具體實(shí)現(xiàn)了
then方法中onFulfilled, onRejected的返回值會(huì)作為新promise的執(zhí)行結(jié)果onFulfilled, onRejected這兩個(gè)函數(shù)要在promise的狀態(tài)變?yōu)閜ending或resolved的時(shí)候才能分別執(zhí)行
所以如果promise方法狀態(tài)為resolved或rejected的話,我們就可以直接在then方法中執(zhí)行resolve(onFulfilled(param))和reject(onRejected(param))
this.then = function (onFulfilled, onRejected) { // 返回一個(gè)新的promise對(duì)象 return new self.constructor(function (resolve, reject) { if (state === true) { // param是promise對(duì)象完成后的結(jié)果 resolve(onFulfilled(param)) } else if (state === false) { reject(onRejected(param)) } else { // 沒有執(zhí)行完畢,怎么辦 } }) }
但如果promise的狀態(tài)為pending呢
由于原始promise的狀態(tài)我們是無法動(dòng)態(tài)獲取的,因此我們就需要在他執(zhí)行狀態(tài)改變的時(shí)候同時(shí)執(zhí)行onFulfilled和onRejected方法
我們可以把這個(gè)方法放在原始promise對(duì)象的resolve和reject方法中執(zhí)行
因此我們要在promise的對(duì)象定義中添加四個(gè)參數(shù),分別記錄onFulfilled和onRejected,以及then方法返回的新promise對(duì)象的resolve和reject
然后如果執(zhí)行then方法的時(shí)候promise對(duì)象的狀態(tài)為pending的話,就將上述四個(gè)參數(shù)記錄起來
// then方法返回的promise對(duì)象的resolve和reject var nextResolve = null var nextReject = null // 記錄then方法的參數(shù),onFulfilled和onRejected var asynconFulfilled = null var asynconRejected = null //then方法 this.then = function (onFulfilled, onRejected) { // 返回一個(gè)新的promise對(duì)象 return new self.constructor(function (resolve, reject) { if (state === true) { // param是promise對(duì)象完成后的結(jié)果 resolve(onFulfilled(param)) } else if (state === false) { reject(onRejected(param)) } else { nextResolve = resolve nextReject = reject asynconFulfilled = onFulfilled asynconRejected = onRejected } }) }
接下來就是原始promise中的resolve和reject的重新實(shí)現(xiàn)
// resolve方法 function resolve(data) { // 改變狀態(tài) state = true param = data nextResolve(asynconFulfilled(param)) } // reject方法 function reject(err) { state = false param = err nextReject(asynconRejected(param)) }
很簡(jiǎn)單不是嗎
我們繼續(xù)
上述實(shí)現(xiàn)我們一直沒有考慮一個(gè)很重要的情況,如果then方法返回的還是一個(gè)promise對(duì)象,那么如果我們后邊還有then方法的話就要等待前一個(gè)then方法中的promise對(duì)象的狀態(tài)從pending變?yōu)橥瓿?br>這要怎么做呢
什么時(shí)候可以認(rèn)為then方法返回的promise對(duì)象執(zhí)行完畢了呢,這里我們就要用到then方法(@_@,邊寫邊用...),
以resolve方法為例
var self = this // resolve方法 function resolve(data) { // 記錄onFulfilled的執(zhí)行結(jié)果 let parmise // 改變狀態(tài) state = true param = data // 執(zhí)行記錄的onFulfilled parmise = asynconFulfilled(param) if(parmise === undefined){ // 如果parmise為undefined,就不能解析parmise.constructor } else if (parmise.constructor === self.constructor) { // 等待傳遞進(jìn)來的promise對(duì)象執(zhí)行完畢,然后根據(jù)傳遞進(jìn)來的promise對(duì)象的狀態(tài)執(zhí)行resolve或reject // 注意,這個(gè)param是形參,在then方法的promise中執(zhí)行 promise.then(function (param) { resolve(param) }, function (param) { reject(param) }) } else { // 這個(gè)是前邊的then返回的不是promise對(duì)象的情況 resolve(promise) } }
前面我們忽略了兩點(diǎn) (then方法接收兩個(gè)可選的參數(shù)(onFulfilled, onRejected)) 和 (then方法傳進(jìn)來的參數(shù)必須是函數(shù),如果不是就要忽略)
var self = this // resolve方法 function resolve(data) { // 記錄onFulfilled的執(zhí)行結(jié)果 var parmise // 改變狀態(tài) state = true param = data // 執(zhí)行記錄的onFulfilled // begin-------------- if (typeof onFulfilled === "function") { promise = onFulfilled(param) if (promise === undefined) { // 待補(bǔ)充 } else if (promise.constructor === self.constructor) { // 注意,這個(gè)param是形參,在then方法的promise中執(zhí)行 promise.then(function (param) { resolve(param) }, function (param) { reject(param) }) } else { reject(promise) } } else { // 如果onFulfilled不是function,忽略,直接resolve或reject resolve(param) } // ---------------end }
上面begin到end之間的代碼還要在then方法調(diào)用,所以我們可以把這段代碼抽象為一個(gè)函數(shù)
resolve 和 reject的原理相同,只要注意如果不是function 的話需要執(zhí)行reject
onFulfilled和?onRejected只有在[執(zhí)行環(huán)境]堆棧僅包含平臺(tái)代碼時(shí)才可被調(diào)用
所以將上述begin-end之間的代碼放到seTimeout中執(zhí)行(瀏覽器環(huán)境)
function resolve(data) { // 記錄onFulfilled的執(zhí)行結(jié)果 var parmise // 改變狀態(tài) state = true param = data // 執(zhí)行記錄的onFulfilled window.setTimeout(function () { // begin-------------- // 上述代碼 // ---------------end }, 0) }
下面是完整代碼
注:沒有實(shí)現(xiàn)正確的事件循環(huán)
// 簡(jiǎn)單實(shí)現(xiàn)ES6 Promise function MyPromise(callback) { // 保存this值 var self = this // 記錄狀態(tài)null為pending,true為resolved,false為reject var state = null // 記錄resolve的參數(shù) var param = null // then方法返回的promise對(duì)象的resolve和reject var nextResolve = null var nextReject = null // 記錄then方法的參數(shù),onFulfilled和onRejected var asynconFulfilled = null var asynconRejected = null // 執(zhí)行并改變promise對(duì)象狀態(tài) callback(resolve, reject) // then方法 this.then = function (onFulfilled, onRejected) { // 返回一個(gè)新的promise對(duì)象 return new self.constructor(function (resolve, reject) { // 判斷異步代碼是否執(zhí)行完畢(是否resolve或reject) // 若執(zhí)行完畢就在then方法中立即執(zhí)行,否則將四個(gè)參數(shù)記錄下來,等待state就緒后再執(zhí)行doAsyn*函數(shù) if (state === true) { doAsynconFulfilled(onFulfilled, resolve, reject) } else if (state === false) { doAsynconRejected(onRejected, resolve, reject) } else { nextResolve = resolve nextReject = reject asynconFulfilled = onFulfilled asynconRejected = onRejected } }) } // resolve方法 function resolve(data) { // 改變狀態(tài) state = true param = data if(nextResolve){ doAsynconFulfilled(asynconFulfilled, nextResolve, nextReject) } } // reject方法 function reject(err) { state = false param = err if(nextReject){ doAsynconRejected(asynconRejected, nextResolve, nextReject) } } // 核心方法(我覺得是) function doAsynconFulfilled(onFulfilled, resolve, reject) { window.setTimeout(function () { // 判斷onFulfilled是否為function,不是則忽略 if (typeof onFulfilled === "function") { // 執(zhí)行onFulfilled方法獲取返回值promise() let promise = onFulfilled(param) // 如果promise為undefined 執(zhí)行 if // 如果promise為MyPromise對(duì)象 執(zhí)行 else if // 如果promise為非MyPromise對(duì)象 執(zhí)行 else if (promise === undefined) { resolve(param) // 待補(bǔ)充 } else if (promise.constructor === self.constructor) { // 等待傳遞進(jìn)來的promise對(duì)象執(zhí)行完畢,然后根據(jù)傳遞進(jìn)來的promise對(duì)象的狀態(tài)執(zhí)行resolve或reject promise.then(function (param) { resolve(param) }, function (param) { reject(param) }) } else { // 執(zhí)行then方法返回的對(duì)象的resolve resolve(promise) } } else { // 傳遞參數(shù) resolve(param) } }, 0) } function doAsynconRejected(onRejected, resolve, reject) { window.setTimeout(function () { if (typeof onRejected === "function") { let promise = onRejected(param) if (promise === undefined) { reject(param) // 待補(bǔ)充 } else if (promise.constructor === self.constructor) { promise.then(function (param) { resolve(param) }, function (param) { reject(param) }) } else { reject(promise) } } else { // 傳遞錯(cuò)誤信息 reject(param) } }, 0) } } // 測(cè)試使用 var b = function (message) { return new MyPromise(function (resolve, reject) { document.body.onclick = function () { resolve("click:" + message) } }) } var a = new MyPromise(function (resolve, reject) { resolve(123) }).then(function (message) { return b(message) }).then().then(function (message) { console.log("final:" + message) },function (err) { console.log("final:" + err) }) console.log("window")
當(dāng)然還有Promise.all等方法。
完畢!
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/107803.html
摘要:的翻譯文檔由的維護(hù)很多人說,阮老師已經(jīng)有一本關(guān)于的書了入門,覺得看看這本書就足夠了。前端的異步解決方案之和異步編程模式在前端開發(fā)過程中,顯得越來越重要。為了讓編程更美好,我們就需要引入來降低異步編程的復(fù)雜性。 JavaScript Promise 迷你書(中文版) 超詳細(xì)介紹promise的gitbook,看完再不會(huì)promise...... 本書的目的是以目前還在制定中的ECMASc...
摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復(fù)雜性。寫一個(gè)符合規(guī)范并可配合使用的寫一個(gè)符合規(guī)范并可配合使用的理解的工作原理采用回調(diào)函數(shù)來處理異步編程。 JavaScript怎么使用循環(huán)代替(異步)遞歸 問題描述 在開發(fā)過程中,遇到一個(gè)需求:在系統(tǒng)初始化時(shí)通過http獲取一個(gè)第三方服務(wù)器端的列表,第三方服務(wù)器提供了一個(gè)接口,可通過...
摘要:回調(diào)函數(shù)這是異步編程最基本的方法。對(duì)象對(duì)象是工作組提出的一種規(guī)范,目的是為異步編程提供統(tǒng)一接口。誕生后,出現(xiàn)了函數(shù),它將異步編程帶入了一個(gè)全新的階段。 更多詳情點(diǎn)擊http://blog.zhangbing.club/Ja... Javascript 語言的執(zhí)行環(huán)境是單線程的,如果沒有異步編程,根本沒法用,非卡死不可。 為了解決這個(gè)問題,Javascript語言將任務(wù)的執(zhí)行模式分成兩種...
摘要:和和都有和,但是略有不同。實(shí)際上返回的是一個(gè)對(duì)象。和添加的回調(diào),添加的回調(diào)。所以在調(diào)用成功的情況下執(zhí)行添加的回調(diào),調(diào)用失敗時(shí)執(zhí)行添加的回調(diào)。,產(chǎn)生對(duì)象并,產(chǎn)生對(duì)象并,然后繼續(xù)處理,的語法糖,和的差不多但不同。 Deferred 和 Promise ES6 和 jQuery 都有 Deffered 和 Promise,但是略有不同。不過它們的作用可以簡(jiǎn)單的用兩句話來描述 Deffere...
摘要:本篇文章將會(huì)嘗試用簡(jiǎn)單易懂的語言描述的原理,并且用手?jǐn)]一個(gè)簡(jiǎn)單的。一個(gè)后可以通過方法,指定和時(shí)的回調(diào)函數(shù)。實(shí)現(xiàn)實(shí)現(xiàn)狀態(tài)機(jī)因?yàn)槭且粋€(gè)構(gòu)造函數(shù),使用的寫法,首先想到的就是有顯式聲明的。 說到Promise,都知道它是比回調(diào)函數(shù)更優(yōu)的一種異步編程解決方案,它可以使得異步操作邏輯變得更加清晰,是解決地獄回調(diào)的一種嘗試。本篇文章將會(huì)嘗試用簡(jiǎn)單易懂的語言描述Promise的原理,并且用es6手?jǐn)]一...
閱讀 2702·2023-04-25 17:58
閱讀 2986·2021-11-15 11:38
閱讀 2382·2021-11-02 14:48
閱讀 1194·2021-08-25 09:40
閱讀 1828·2019-08-30 15:53
閱讀 1100·2019-08-30 15:52
閱讀 1038·2019-08-30 13:55
閱讀 2440·2019-08-29 15:21