js在進行異步操做時,常常會使用promise來獲取異步操做的返回結果,那promise內部到底是如何實現的?api
本文經過手寫一個符合promise A+規範的promise類,來深刻了解promise的實現邏輯。數組
promise A+規範,是一個開源的、可被開發者實現的標準promise規範,規定了實現一個標準的promise具體須要實現哪些功能。promise
具體實現功能細則參考:promises A+規範瀏覽器
大概分爲兩種:異步
Promise.all, Promise.resolve, Promise.reject, Promise.race函數
then/catch/finally測試
let promise = new Promise(function(resolve, reject) {
// 若是作什麼異步操做成功了
setTimeout(() => {
let isSuccess = true
if (isSuccess) {
resolve('接口返回成功了')
} else {
reject('接口返回失敗了')
}
}, 1000)
})
promise.then(value => {
console.log('success', value)
}, error => {
console.log('error', error)
})
// 日誌打印
// -> 接口返回成功了
複製代碼
如何實現一個promiseui
能夠看到promise是一個類,裏面傳遞一個帶了resolve和reject參數的函數,這個函數叫作executor執行器,executor中包含了一個resolve函數和一個reject函數。this
具體實現:spa
// 定義promise的三種狀態常量
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
function Promise(executor) {
// 初始化promise狀態和value值
let that = this
that.status = PENDING
that.value = undefined
// resolve執行時,將狀態置爲成功態
function resolve(value) {
// 只有狀態爲pending時,status修改成fulfilled,同時更新value的值
if (that.status === PENDING) {
that.status = FULFILLED
that.value = value
}
}
// reject執行時,將狀態置爲失敗態
function reject(reason) {
if (that.status === PENDING) {
that.status = REJECTED
that.value = reason
}
}
executor(resolve, reject)
}
Promise.prototype.then = function(onFulfilled, onRejected) {
let that = this
// 若是當前狀態爲已完成,則執行完成的回調
if (that.status === FULFILLED) {
onFulfilled(that.value)
}
// 若是當前狀態爲已失敗,則執行失敗的回調
if (that.status === REJECTED) {
onRejected(that.value)
}
}
複製代碼
一個簡單的promise實現就已經完成,包含new Promise(executor: (resolve, reject) => void)的實現,而且支持then調用的邏輯來獲取value或者reason。
可是該實現還不支持異步resolve或者reject狀態
前面實現的promise,還有一個問題,就是executor執行器裏的resolve若是延遲執行,好比延遲1000ms後再執行,當promise.then優先於resolve或者reject執行,此時該promise的status仍是pending狀態,不會執行then裏面的onFulfilled和onRejected方法
因此這裏咱們要使用發佈/訂閱者模式,將promise.then裏面的onFulfilled和onRejected兩個監聽方法存儲起來,在promise的狀態resolve或者reject時再通知對應的監聽方法
添加發布/訂閱者模式
// 定義promise的三種狀態常量
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
function Promise(executor) {
// 初始化promise狀態和value值
let that = this
that.status = PENDING
that.value = undefined
// 初始化訂閱resolve和rejecte方法的回調數組
that.onFulfilledCallbacks = []
that.onRejectedCallbacks = []
// resolve執行時,將狀態置爲成功態
function resolve(value) {
// 只有狀態爲pending時,status修改成fulfilled,同時更新value的值
if (that.status === PENDING) {
that.status = FULFILLED
that.value = value
// 執行訂閱了resolve的回調方法
that.onFulfilledCallbacks.forEach(onFulfilled => onFulfilled(that.value))
}
}
// reject執行時,將狀態置爲失敗態
function reject(reason) {
if (that.status === PENDING) {
that.status = REJECTED
that.value = reason
// 執行訂閱了reject的回調方法
that.onRejectedCallbacks.forEach(onRejected => onRejected(that.value))
}
}
executor(resolve, reject)
}
Promise.prototype.then = function(onFulfilled, onRejected) {
let that = this
// 若是當前狀態爲已完成,則執行完成的回調
if (that.status === FULFILLED) {
onFulfilled(that.value)
}
// 若是當前狀態爲已失敗,則執行失敗的回調
if (that.status === REJECTED) {
onRejected(that.value)
}
// 若是當前狀態還在pending,則將回調方法添加到訂閱狀態的回調中
if (that.status === PENDING) {
// 訂閱resolve的回調
that.onFulfilledCallbacks.push(onFulfilled)
// 訂閱reject的回調
that.onRejectedCallbacks.push(onRejected)
}
}
複製代碼
好的,如今咱們實現的promise已經很是強大了,能夠寫一個簡單的測試用例,跑一下。
let promise1 = new Promise(function(resolve, reject) {
resolve('promise1-直接返回成功')
})
let promise2 = new Promise(function(resolve, reject) {
setTimeout(() => {
reject('promise2-異步返回成功')
}, 1000)
})
let promise3 = new Promise(function(resolve, reject) {
resolve('promise3-直接返回成功')
reject('promise3-直接返回失敗')
})
promise1.then((value) => {
console.log('promise1-執行了onFulfilled', value)
}, (reason) => {
console.log('promise1-執行了onRejected', reason)
})
promise2.then((value) => {
console.log('promise2-執行了onFulfilled', value)
}, (reason) => {
console.log('promise2-執行了onRejected', reason)
})
promise3.then((value) => {
console.log('promise3-執行了onFulfilled', value)
}, (reason) => {
console.log('promise3-執行了onRejected', reason)
})
// 執行結果
// -> promise1-執行了onFulfilled promise1-接口返回成功了
// -> promise3-執行了onFulfilled promise3-接口返回成功了
// 1000ms後
// -> promise2-執行了onRejected promise2-異步返回成功
複製代碼
測試結果符合要求
promise1經過resolve,直接觸發then裏的onFulfilled,打印promise1-執行了onFulfilled promise1-接口返回成功了
promise2經過延遲觸發reject,延遲1000ms後觸發了onRejected,打印promise2-執行了onRejected
promise3先resolve再reject,因爲resolve後當前promise狀態會更新爲fulfilled,因此後面再執行reject會無效,直接打印promise3-執行了onFulfilled
目前咱們的promise實現瞭如下功能:
這就是一個簡單的符合promise A+規範promise實現,不過promise還有許多其餘的功能特性和api,好比:Promise.resolve,Promise.reject,Promise.all等,我會在後面的文章中更新。
未完待續...