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