您好,登錄后才能下訂單哦!
這篇“JavaScript怎么實現(xiàn)簡易的Promise對象”文章的知識點大部分人都不太理解,所以小編給大家總結(jié)了以下內(nèi)容,內(nèi)容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“JavaScript怎么實現(xiàn)簡易的Promise對象”文章吧。
實現(xiàn)一個簡易的Promise對象,我們首先要了解幾個相關(guān)的知識點:
Promise對象的狀態(tài): pending(進行中)、fulfilled(已成功)和rejected(已失?。?。只有異步操作的結(jié)果,可以決定當前是哪一種狀態(tài),任何其他操作都無法改變這個狀態(tài)。這也是Promise這個名字的由來,它的英語意思就是“承諾”,表示其他手段無法改變。
Promise的參數(shù): Promise構(gòu)造函數(shù)接收一個函數(shù)作為參數(shù),函數(shù)內(nèi)部有兩個參數(shù),分別是resolve和reject,這兩個參數(shù)是兩個函數(shù),由JS引擎提供,不需要我們部署。reslove函數(shù)
的作用是將Promise對象的狀態(tài)由 'pending' 狀態(tài)變?yōu)?'resolved'狀態(tài)即('fulfilled'狀態(tài)),方便與參數(shù)名對應(yīng),reject函數(shù)
的作用是將Promise對象的狀態(tài)由 'pending' 狀態(tài)變?yōu)?'rejected'狀態(tài)。
但是我們應(yīng)該注意的是,Promise對象的狀態(tài)一經(jīng)改變,就不再發(fā)生改變(即pending
--> resolved
|| pending
--> rejected
其中任意一種發(fā)生改變之后,Promise對象的狀態(tài)將不再發(fā)生改變)
let p1 = new Promise((resolve, reject) => { resolve('成功'); reject('失敗'); throw('報錯'); //相當于reject() }) console.log(p1);
讓我們看看三種狀態(tài)的打印的結(jié)果分別是什么吧
class myPromise { constructor(executor) { this.status = 'pending'; // 變更promise的狀態(tài) this.value = null; executor(this.resolve, this.reject); // new 一個myPromise 得到的實例對象里面有兩個函數(shù) } resolve(value) { if (this.status !== 'pending') return; this.status = 'fulfilled'; // 變更promise的狀態(tài) this.value = value; } reject(reason) { if (this.status !== 'pending') return this.status = 'rejected'; this.value = reason; } }
貌似這么寫代碼邏輯也說得通,那么讓我們看一下實現(xiàn)的效果:
看到這里,不難想到我們的resolve和reject的兩個方法的this
指向出現(xiàn)了問題,我們仔細看看不難發(fā)現(xiàn),這兩個方法被我們作為實參放到了構(gòu)造器函數(shù),此時this的指向是指向了構(gòu)造器函數(shù),而不是我們寫的myPromise這個構(gòu)造函數(shù)身上,那只需要bind
顯示綁定一下this 的指向就可以解決了。
executor(this.resolve.bind(this), this.reject.bind(this))
并且myPromise的狀態(tài)一經(jīng)變更也不再改變,是不是有一點原裝Promise的味道了。但是在Promise里面還有一個錯誤捕捉機制,只要promise里面執(zhí)行的邏輯報錯了,就需要走reject邏輯,將錯誤拋出來,那我們只需要使用try catch來實現(xiàn)就可以。
try { executor(this.resolve.bind(this), this.reject.bind(this)); } catch (error) { this.reject(error) }
這樣我們就實現(xiàn)了極簡版的Promise對象,但是通常情況下我們都是使用Promise對象來處理異步的問題,說到異步,那不得不提起Promise.prototype.then()
這個方法了,then
方法返回的是一個新的Promise實例
(注意,不是原來那個Promise實例)。因此可以采用鏈式寫法,即then方法后面再調(diào)用另一個then方法。
then方法的第一個參數(shù)是`resolved狀態(tài)的回調(diào)函數(shù)`,第二個參數(shù)是`rejected狀態(tài)的回調(diào)函數(shù)`,它們都是可選的。
當promise的狀態(tài)為'fulfilled'會執(zhí)行第一個回調(diào)函數(shù),當狀態(tài)為'rejected'時執(zhí)行第二個回調(diào)函數(shù)。
必須等到Promise的狀態(tài)變更過一次之后,狀態(tài)為'fulfilled'或者'rejected',才去執(zhí)行then里面的邏輯。
.then支持鏈式調(diào)用,下一次.then受上一次.then執(zhí)行結(jié)果的影響。
知道以上這幾點,我們就可以嘗試如何實現(xiàn).then方法了
class myPromise { constructor(executor) { this.status = 'pending'; this.value = null; this.onFulfilledCallbacks = []; // 用來保存成功的回調(diào)(處理異步) this.onRejectedCallbacks = []; // 用來保存失敗的回調(diào)(處理異步) try { executor(this.resolve.bind(this), this.reject.bind(this)); } catch (error) { this.reject(error) } } resolve(value) { if (this.status !== 'pending') return; this.status = 'fulfilled'; this.value = value; // 調(diào)用then里面的回調(diào) while (this.onFulfilledCallbacks.length) { // 當異步成功回調(diào)數(shù)組中存在回調(diào)函數(shù),那就執(zhí)行 this.onFulfilledCallbacks.shift()(this.value) } } reject(reason) { if (this.status !== 'pending') return this.status = 'rejected'; this.value = reason; while (this.onRejectedCallbacks.length) { // 當異步失敗回調(diào)數(shù)組中存在回調(diào)函數(shù),那就執(zhí)行 this.onRejectedCallbacks.shift()(this.value) } } then(onFulfilled, onRejected) { onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val // 判斷.then的第一個參數(shù)是不是一個函數(shù),如果不是就直接作為結(jié)果返回 onRejected = typeof onRejected === 'function' ? onRejected : val => { throw val } // 判斷.then的第二個參數(shù)是不是一個函數(shù),如果不是就直接作為錯誤返回 var thenPromise = new myPromise((resolve, reject) => { // 因為.then返回的是一個心的Promise對象 const resolvePromise = callback => { // 用于判斷回調(diào)函數(shù)的類型 setTimeout(() => { // 讓整個回調(diào)函數(shù)比同步代碼晚一點執(zhí)行,官方不是使用setTimeout實現(xiàn) try { const x = callback(this.value); if (x === thenPromise) { // 你正在返回自身 throw new Error('不允許返回自身!'); } if (x instanceof myPromise) { // 返回的是一個Promise對象 x.then(resolve, reject); } else { // 直接返回一個值,作為resolve的值,傳遞給下一個.then resolve(x); } } catch (error) { reject(error); throw new Error(error) } }) } if (this.status === 'fulfilled') { resolvePromise(onFulfilled) } else if (this.status === 'rejected') { resolvePromise(onRejected) } else if (this.status === 'pending') { this.onFulfilledCallbacks.push(resolvePromise.bind(this, onFulfilled)); this.onRejectedCallbacks.push(resolvePromise.bind(this, onRejected)); } }) return thenPromise } }
以上就是關(guān)于“JavaScript怎么實現(xiàn)簡易的Promise對象”這篇文章的內(nèi)容,相信大家都有了一定的了解,希望小編分享的內(nèi)容對大家有幫助,若想了解更多相關(guān)的知識內(nèi)容,請關(guān)注億速云行業(yè)資訊頻道。
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。