promise 是 es6 新增的乙個內建物件,用來避免**地獄的一種解決方案,相比**函式,使用promise 處理非同步流程可以使**層次清晰,便於理解,配合 async/await 語法糖更是直接以同步的方式寫非同步**,再也不用擔心**地獄了。
promise 有3種狀態:pending、fulfilled、rejected。乙個 promise 最初的狀態是 pending,在 resolve 被呼叫時變為 fulfilled,或者在 reject 被呼叫時變為 rejected。可以簡單理解為 promise 就是乙個發布訂閱模型,通過 then 方法註冊狀態改變時的**函式,當 promise 的狀態改變時呼叫註冊的**函式並返回新的 promise。
目前 promise 的主流規範主要是 promises/a+,對照標準就可以實現乙個完整的 promise,本文只是對 promise 的簡單實現,複雜情況暫時先不考慮。
promise 的主要邏輯就是對其內部狀態的維護,要實現乙個 promise,需要定義一些屬性來儲存狀態。
function promise ()
promise 的建構函式接受乙個帶有 resolve 和 reject 兩個引數的函式,先把它稱之為 executor,promise 建構函式執行時立即呼叫 executor 並傳遞 resolve 和 reject 兩個函式作為引數,resolve 和 reject 函式被呼叫時,會分別將 promise 的狀態改變為 fulfilled 或者 rejected,如果 executor 中丟擲乙個錯誤,promise 狀態也會變為 rejected。了解了這些,接下來繼續完善 promise 的建構函式。
function promise (executor) catch (e)
}
瀏覽器中的 resolve 和 reject 函式是使用原生**在j**ascript虛擬機器中實現的,這裡需要我們自己實現。resolve 和 reject 主要的功能就是改變promise的狀態,然後觸發**函式,這裡我們把 resolve 和 reject 定義在 promise 的原型上。
promise.prototype.resolve = function(value) )
}promise.prototype.reject = function(reason) )
}
then 方法用來註冊 promise 狀態確定後的**,then 方法最多需要 onfulfilled, onrejected 兩個引數:分別對應 promise 的成功和失敗情況的**函式,並返回乙個新的promise。對應不同的狀態,呼叫 then 方法執行的邏輯也不一致。
根據規範:如果 onfulfilled 或 onrejected 的返回結果是 promise,那麼 then 返回的 promise 的狀態與之相同。
promise.prototype.then = function(onfulfilled, onrejected)
onfulfilled = typeof onfulfilled === 'function' ? onfulfilled : defaultfn
onrejected = typeof onrejected === 'function' ? onrejected : defaultfn
if (_this.status === 'fulfilled') else })}
if (_this.status === 'rejected') else })}
if (_this.status === 'pending') else
} catch (e)
})_this.onrejectedcallback.push(function(reason) else
} catch (e)
})})
}}
順便實現 catch 方法
promise.prototype.catch = function(onrejected)
promise 建構函式中傳入的 executor 函式會立即執行,但是 then 方法中傳入的 onfulfilled, onrejected 函式需要非同步延遲呼叫,promise/a+ 規範中解釋:實踐中要確保 onfulfilled 和 onrejected 方法非同步執行,且應該在 then 方法被呼叫的那一輪事件迴圈之後的新執行棧中執行。這個事件佇列可以採用巨集任務 macro-task 機制或微任務 micro-task 機制來實現。
因此即便乙個 promise 立即被 resolve,在 then 之後的**也會在 onfulfilled, onrejected 前面執行,如下例列印結果是1,3,2 而不是 1,2,3 。
let promise = new promise((resolve, reject) => )
promise.then(() => )
console.log(3)
// 列印結果
// 1
// 3
// 2
在瀏覽器中 onfulfilled 和 onrejected 的非同步執行是使用微任務機制實現的,我們使用巨集任務settimeout 來實現非同步執行,稍微修改一下 resolve、reject 的實現**。
promise.prototype.resolve = function(value) )
})}promise.prototype.reject = function(reason) )
}, 0)
}
let promise = new promise((resolve, reject) => , 1000)
})promise.then(v => ).then(v => , 1000)
})}).then(v => )
列印結果
start12
3
簡單promise實現原理
promise可以有三種狀態,分別是pedding fulfilled rejected pending promise物件例項建立時候的初始狀態 fulfilled 可以理解為成功的狀態 rejected可以理解為失敗的狀態 構造乙個promise例項需要給promise建構函式傳入乙個函式。傳入...
簡單實現Promise原理
const pending pending const resolved resolved const rejected rejected 對於不太經常更改的變數 定於為常量 function mypromise fn function reject value trycatch e mypromi...
Promise的簡單實現
promise 是非同步程式設計的一種解決方案 從語法上講,promise是乙個物件,從它可以獲取非同步操作的訊息 從本意上講,它是承諾,承諾它過一段時間會給你乙個結果。promise有三種狀態 pending 等待態 fulfiled 成功態 rejected 失敗態 狀態一旦改變,就不會再變。創...