寫在前面
沒(méi)錯(cuò),這又是一篇關(guān)于手寫 Promise 的文章,想必大家已經(jīng)看過(guò)很多相關(guān) Promise 的文章,關(guān)于一些 Promise 出現(xiàn)原因等問(wèn)題我就不詳細(xì)說(shuō)了,網(wǎng)上有很多資料。這次我們使用 typescript,從 ES6 中的 Promise 類型定義入手,分析 Promise 及相關(guān)方法的傳入?yún)?shù)和返回值,手寫一個(gè) typescript 版本的 Promise。
Promise/A+ 規(guī)范
Promise/A+ 規(guī)范是業(yè)內(nèi)所有的 Promise 類庫(kù)的統(tǒng)一規(guī)范,我們要寫的 Promise 也要符合這一規(guī)范(英文文檔請(qǐng)查看 Promises/A+,相關(guān)中文翻譯 Promise A+ 規(guī)范,感謝譯者)。
由于內(nèi)容過(guò)多,在下面的編碼中會(huì)一一進(jìn)行實(shí)現(xiàn),這里先提出幾個(gè)術(shù)語(yǔ):
-
解決(fulfill):指一個(gè) promise 成功時(shí)進(jìn)行的一系列操作,如狀態(tài)的改變、回調(diào)的執(zhí)行。雖然規(guī)范中用
fulfill來(lái)表示解決,但在后世的 promise 實(shí)現(xiàn)多以resolve來(lái)指代之。 - 拒絕(reject):指一個(gè) promise 失敗時(shí)進(jìn)行的一系列操作。
- 終值(eventual value):所謂終值,指的是 promise 被解決(fulfill)時(shí)傳遞給解決回調(diào)的值,由于 promise 有一次性的特征,因此當(dāng)這個(gè)值被傳遞時(shí),標(biāo)志著 promise 等待態(tài)的結(jié)束,故稱之終值,有時(shí)也直接簡(jiǎn)稱為值(value)。
- 據(jù)因(reason):也就是拒絕原因,指在 promise 被拒絕(reject)時(shí)傳遞給拒絕回調(diào)的值。
值得注意的是,核心的 Promises/A+ 規(guī)范不設(shè)計(jì)如何創(chuàng)建、解決和拒絕 promise,而是專注于提供一個(gè)通用的 then 方法。所以,完成了對(duì)于then方法的交互,其實(shí)也就基本完成了對(duì)于 Promises/A+ 規(guī)范的實(shí)現(xiàn)。
實(shí)現(xiàn) Promise
基本功能
首先我們要實(shí)現(xiàn) Promise 的基本功能,傳入生成器,reslove和reject函數(shù)的執(zhí)行以及調(diào)用then函數(shù)對(duì)于值的基本獲取,先來(lái)看看構(gòu)造函數(shù)的類型定義:
// 這是類本身,還有 all, race 等方法在這里面定義
interface PromiseConstructor {
/**
* A reference to the prototype.
*/
readonly prototype: Promise<any>;
/**
* Creates a new Promise.
* @param executor A callback used to initialize the promise. This callback is passed two arguments:
* a resolve callback used to resolve the promise with a value or the result of another promise,
* and a reject callback used to reject the promise with a provided reason or error.
*/
// 這里就是重點(diǎn)部分了
new <T>(executor: (resolve: (value?: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void): Promise<T>;
// ...
}
上面我們會(huì)看到兩個(gè)其余的接口類型,分別是Promise<T>和PromiseLike<T>,其中Promise<T>就是實(shí)例對(duì)象的相關(guān)屬性接口:
// 這時(shí)實(shí)例對(duì)象,下面只是 ES2015 的接口屬性,因?yàn)楹罄m(xù) Promise 做過(guò)更新,后續(xù)會(huì)說(shuō)明更多實(shí)例屬性
interface Promise<T> {
/**
* Attaches callbacks for the resolution and/or rejection of the Promise.
* @param onfulfilled The callback to execute when the Promise is resolved.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of which ever callback is executed.
*/
then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;
//...
}
PromiseLike<T>的接口在下面:
interface PromiseLike<T> {
/**
* Attaches callbacks for the resolution and/or rejection of the Promise.
* @param onfulfilled The callback to execute when the Promise is resolved.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of which ever callback is executed.
*/
then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): PromiseLike<TResult1 | TResult2>;
}
可以看出PromiseLike接口定義的就是一個(gè)擁有then()方法的對(duì)象(官方的叫法是 thenable),只要有then()方法就會(huì)將其當(dāng)做一個(gè)Promise實(shí)例看待。
// 試驗(yàn)一下
new Promise((resolve) => {
resolve({
prop: 'common property',
// 這里我們自己構(gòu)造了個(gè) then 方法,Promise 會(huì)自動(dòng)為 then 方法 reslove 和 reject 函數(shù)
then(reslove2: any) {
reslove2('promiselike')
}
})
}).then((res) => {
// 果然,被當(dāng)做成了 Promise
console.log(res) // promiselike
})
需要注意的是,Promise 內(nèi)部的回調(diào)函數(shù)的異步執(zhí)行機(jī)制是使用的微任務(wù),而我們所使用的環(huán)境中并沒(méi)有為我們提供微任務(wù)的相關(guān) api,所以代碼中都是使用setTimeout進(jìn)行異步模擬,將回調(diào)直接推入到事件環(huán)的最后。
如果對(duì)事件環(huán)與微任務(wù)不太了解,可以查看下這篇文章 徹底搞懂 JS 事件輪詢 。
下面是代碼實(shí)現(xiàn):
// 創(chuàng)建一枚舉類型保存響應(yīng)狀態(tài)的變量
enum Status {
PENDING = 'pending',
FULFILLED = 'fulfilled',
REJECTED = 'rejected'
}
// 將需要類型提出來(lái)
type Resolve<T> = (value: T | PromiseLike<T>) => void
type Reject = (reason?: any) => void
type Executor<T> = (resolve: Resolve<T>, reject: Reject) => void
type onFulfilled<T, TResult1> =
| ((value: T) => TResult1 | PromiseLike<TResult1>)
| undefined
| null
type onRejected<TResult2> =
| ((reason: any) => TResult2 | PromiseLike<TResult2>)
| undefined
| null
/*
將判斷是否為 thenable 單獨(dú)提出來(lái),減少代碼冗余,不然每次都需要使用:
((typeof value === 'object' && value !== null) ||
typeof value === 'function') && typeof (value as PromiseLike<T>).then === 'function'
來(lái)進(jìn)行判斷,同時(shí)也有更好的 typescript 提示
*/
function isPromise(value: any): value is PromiseLike<any> {
return (
((typeof value === 'object' && value !== null) ||
typeof value === 'function') &&
typeof value.then === 'function'
)
}
class MyPromise<T> {
// 剛開始的狀態(tài)
status: Status = Status.PENDING
// 保存當(dāng)前 Promise 的終值,這里讓它一定會(huì)有值
private value!: T
// 保存當(dāng)前 Promise 的據(jù)因
private reason?: any
private onFulfilledCallback: (() => void)[] = [] //成功的回調(diào)
private onRejectedCallback: (() => void)[] = [] //失敗的回調(diào)
constructor(executor: Executor<T>) {
try {
// 防止 this 丟失
executor(this._resolve.bind(this), this._reject.bind(this))
} catch (e) {
// 出錯(cuò)直接 reject
this._reject(e)
}
}
private _resolve(value: T | PromiseLike<T>) {
try{
// 模擬微任務(wù)異步
setTimeout(() => {
// 判斷是否是個(gè) thenable 對(duì)象,如果是,我們直接取 pending 結(jié)束后的值
if (isPromise(value)) {
// 再次將內(nèi)部的 resolve 和 reject 函數(shù)傳入
value.then(this._resolve.bind(this), this._reject.bind(this))
return
}
// 如果是 pending 狀態(tài)就變?yōu)?fulfilled
if (this.status === Status.PENDING) {
this.status = Status.FULFILLED
// 這里的 value 類型只會(huì)是 T
this.value = value
// resolve 后執(zhí)行 .then 時(shí)傳入的回調(diào)
this.onFulfilledCallback.forEach((fn) => fn())
}
})
}catch(err){
// 捕獲如果傳入的是 Promise 時(shí)在內(nèi)部拋出錯(cuò)誤后的捕獲
this._reject(err)
}
}
// 內(nèi)部的 reject 函數(shù),就是我們實(shí)例 Promise 傳入給用戶調(diào)用的 reject
private _reject(reason: any) {
// 大體用法同上,這里不用進(jìn)行值穿透,所以不用判斷是否為 Promise 對(duì)象了
setTimeout(() => {
if (this.status === Status.PENDING) {
this.status = Status.REJECTED
this.reason = reason
this.onRejectedCallback.forEach((fn) => fn())
}
})
}
public then<TResult1 = T, TResult2 = never>(
onfulfilled?: onFulfilled<T, TResult1>,
onrejected?: onRejected<TResult2>
): MyPromise<TResult1 | TResult2> {
// 關(guān)于 onfulfilled 與 onrejected 如果沒(méi)有傳我們需要進(jìn)行值的透?jìng)鳎窃诨竟δ艿膶?shí)現(xiàn)中我們先不管這個(gè)問(wèn)題,默認(rèn)一定會(huì)傳入函數(shù)
// 判斷當(dāng)前狀態(tài),如果是異步 reslove 或 reject,那么此時(shí)的 status 還是 pending
if (this.status === Status.FULFILLED) {
setTimeout(() => {
onfulfilled!(this.value)
})
}
if (this.status === Status.REJECTED) {
setTimeout(() => {
onrejected!(this.reason)
})
}
if (this.status === Status.PENDING) {
// 如果為 pending,需要將 onFulfilled 和 onRejected 函數(shù)都存放起來(lái),狀態(tài)確定后再依次執(zhí)行
// 執(zhí)行回調(diào)的時(shí)候有 setTimeout,這里就不加了
this.onFulfilledCallback.push(() => {
onfulfilled!(this.value)
})
this.onRejectedCallback.push(() => {
onrejected!(this.reason)
})
}
// 鏈?zhǔn)秸{(diào)用,這段代碼現(xiàn)在可以直接無(wú)視,為了不讓 ts 類型報(bào)錯(cuò)加的,因?yàn)?.then 返回一個(gè)的 Promise 的值是依賴上一個(gè) Promise 的狀態(tài)和結(jié)果的
return new MyPromise(() => {})
}
}
OK,上面已經(jīng)完成了一個(gè)只有一條鏈的 Promise,下面做一下測(cè)試:
// 同步
new MyPromise((reslove, reject) => {
reslove('success')
}).then(
(res) => {
console.log(res) // success
},
(err) => {
console.log(err)
}
)
// 異步
new MyPromise((reslove, reject) => {
setTimeout(() => {
reslove('timeout success')
}, 2000)
}).then(
(res) => {
console.log(res) // timeout success
},
(err) => {
console.log(err)
}
)
結(jié)果為立刻打印success,兩秒后打印timeout success,符合我們的預(yù)期。
then 的深入(重點(diǎn))
就如前面所說(shuō),Promise/A+ 規(guī)范的整個(gè)核心都在于對(duì)于then方法的處理。并且還有第三方測(cè)試庫(kù) promises-aplus-tests 測(cè)試我們所寫的 Promise 是否符合規(guī)范,我們后面也會(huì)用使用這個(gè)測(cè)試庫(kù)進(jìn)行測(cè)試。
鏈?zhǔn)秸{(diào)用
要實(shí)現(xiàn)then的鏈?zhǔn)秸{(diào)用,需要返回一個(gè)新的 Promise,同時(shí)不管在then中回調(diào)函數(shù)onfulfilled和onrejected返回了什么值,都可以在這個(gè)新的 Promise 的then方法的回調(diào)函數(shù)參數(shù)中得到。
我們用x來(lái)作為then方法中傳入的onfulfilled或onrejected的返回值,用promise來(lái)表示then方法返回的那個(gè)新的 Promise,依據(jù) Promise/A+ 規(guī)范,我們應(yīng)該對(duì)這段解決過(guò)程 [[Resolve]](promise, x) 做如下操作:
x與promise相等:如果promise和x指向同一對(duì)象,以TypeError為據(jù)因拒絕執(zhí)行promise。x為 Promise:如果x為 Promise ,則使promise接受x的狀態(tài)。
- 如果
x處于等待態(tài),promise需保持為等待態(tài)直至x被執(zhí)行或拒絕- 如果
x處于執(zhí)行態(tài),用相同的值執(zhí)行promise- 如果
x處于拒絕態(tài),用相同的據(jù)因拒絕promisex為對(duì)象或函數(shù)
- 如果
x為對(duì)象或者函數(shù):
- 把
x.then賦值給then- 如果取
x.then的值時(shí)拋出錯(cuò)誤e,則以e為據(jù)因拒絕promise- 如果
then是函數(shù),將x作為函數(shù)的作用域this調(diào)用之。傳遞兩個(gè)回調(diào)函數(shù)作為參數(shù),第一個(gè)參數(shù)叫做resolvePromise,第二個(gè)參數(shù)叫做rejectPromise
- 如果
resolvePromise以值y為參數(shù)被調(diào)用,則運(yùn)行[[Resolve]](promise, y)(就是繼續(xù)遞歸這段解決過(guò)程)- 如果
rejectPromise以據(jù)因r為參數(shù)被調(diào)用,則以據(jù)因r拒絕promise- 如果
resolvePromise和rejectPromise均被調(diào)用,或者被同一參數(shù)調(diào)用了多次,則優(yōu)先采用首次調(diào)用并忽略剩下的調(diào)用- 如果調(diào)用
then方法拋出了異常e:
- 如果
resolvePromise或rejectPromise已經(jīng)被調(diào)用,則忽略之- 否則以
e為據(jù)因拒絕promise- 如果
then不是函數(shù),以x為參數(shù)執(zhí)行promise- 如果
x不為對(duì)象或者函數(shù),以x為參數(shù)執(zhí)行promise
大體的流程圖:

雖然上面看著有點(diǎn)多,其實(shí)大體來(lái)說(shuō)就是讓我們符合以下規(guī)則:
-
如果 then 中的回調(diào)函數(shù)返回一個(gè)值(非 Promise 實(shí)例或是 thenable 對(duì)象)或沒(méi)有返回值(也就是返回 undefined),那么 then 返回的 Promise 將會(huì)成為接受狀態(tài),并且將返回的值作為接受狀態(tài)的回調(diào)函數(shù)(
onfulfilled)的參數(shù)值。new Promise<void>((reslove) => { reslove() }) .then(() => { return 'success' }) .then((res) => { console.log(res) // success }) -
如果 then 中的回調(diào)函數(shù)拋出一個(gè)錯(cuò)誤,那么 then 返回的 Promise 將會(huì)成為拒絕狀態(tài),并且將拋出的錯(cuò)誤作為拒絕狀態(tài)的回調(diào)函數(shù)(
onrejected)的參數(shù)值。new Promise<void>((reslove) => { reslove() }) .then(() => { throw new Error('error message') }) .then( () => {}, (err) => { console.log(err) // Error: error message } )循環(huán)返回 Promise 拋出錯(cuò)誤就像下面這樣 :
const promise2: Promise<any> = new Promise<void>((reslove) => { reslove() }).then(() => { return promise2 }) promise2.then(() => {}, console.log) // [TypeError: Chaining cycle detected for promise #<Promise>] -
如果 then 中的回調(diào)函數(shù)返回一個(gè)已經(jīng)是接受狀態(tài)(fulfilled)的 Promise(我們這里暫且叫做
promise1),那么 then 返回的 Promise 也會(huì)成為接受狀態(tài),并且將promise1中then的回調(diào)函數(shù)的參數(shù)值,作為該被返回的 Promise 的接受狀態(tài)回調(diào)函數(shù)的參數(shù)值。new Promise<void>((reslove) => { reslove() }) .then(() => { return Promise.reslove('success') }) .then((res) => { console.log(res) // success }) -
如果 then 中的回調(diào)函數(shù)返回一個(gè)已經(jīng)是拒絕狀態(tài)(rejected)的 Promise(這里我們暫且叫做
promise2),那么 then 返回的 Promise 也會(huì)成為拒絕狀態(tài),并且將promise2中then的回調(diào)函數(shù)的參數(shù)值,作為該被返回的 Promise 的拒絕狀態(tài)回調(diào)函數(shù)的參數(shù)值。new Promise<void>((reslove) => { reslove() }) .then(() => { return new Promise.reject('error message') }) .then( () => {}, (err) => { console.log(err) // error message } ) -
如果 then 中的回調(diào)函數(shù)返回一個(gè)未定狀態(tài)(pending)的 Promise(這里我們暫且叫做
promise3),那么 then 返回 Promise 的狀態(tài)也是未定的,并且它的終態(tài)與promise3的終態(tài)相同。同時(shí)它變?yōu)榻K態(tài)時(shí)調(diào)用then的回調(diào)函數(shù)參數(shù)與promise3變?yōu)榻K態(tài)時(shí)的回調(diào)函數(shù)的參數(shù)是相同的。new Promise<void>((reslove) => { reslove() }) .then(() => { return new Promise((reslove, reject) => { setTimeout(()=>{ reslove('delay') }, 2000) }) }) .then( res => { console.log(res) // 兩秒后打印 delay } )
好了,照著上面的解決過(guò)程 ,我們來(lái)寫一下這個(gè)處理函數(shù):
function resolvePromise<T>(
promise2: MyPromise<T>,
x: T | PromiseLike<T>,
resolve: Resolve<T>,
reject: Reject
) {
// 不能引用同一個(gè)對(duì)象,不然會(huì)無(wú)限循環(huán)的
if (promise2 === x) {
const e = new TypeError(
'TypeError: Chaining cycle detected for promise #<MyPromise>'
)
// 清空棧信息,不太清楚為什么 Promise 要清除這個(gè),先不管了,繼續(xù)往下
e.stack = ''
// 直接進(jìn)入錯(cuò)誤的回調(diào)
return reject(e)
}
let called = false // 防止多次調(diào)用
// 如果 x 為 Promise,通過(guò)上面的知識(shí)我們知道判斷是否是個(gè) Promise 或者像 Promise 我們是判斷一個(gè)對(duì)象是否有 then 方法,可以發(fā)現(xiàn)在下面判斷是否是對(duì)象或者函數(shù)中也有相同的判斷,所以這里我們可以直接省略
// 如果 x 是對(duì)象或函數(shù)
if ((typeof x === 'object' && x != null) || typeof x === 'function') {
try {
/*
存儲(chǔ)了一個(gè)指向 x.then 的引用,然后測(cè)試并調(diào)用該引用,以避免多次訪問(wèn) x.then 屬性。這種預(yù)防措施確保了該屬性的一致性,因?yàn)槠渲悼赡茉跈z索調(diào)用時(shí)被改變。
注:這里可以用我們封裝的判斷方法 isPromise 判斷,但是既然跟著解決過(guò)程走,那么還是老老實(shí)實(shí)操作一下吧
*/
// 手動(dòng)轉(zhuǎn)一下類型
const then = (x as PromiseLike<T>).then
if (typeof then === 'function') {
// 這里其實(shí)就是調(diào)用傳入的 Promise 的 then 方法,下面代碼就是執(zhí)行了 x.then(()=>{},()=>{})
then.call(
x,
(y) => {
if (called) return
called = true
// 如果是 Promise,我們應(yīng)該遞歸地獲取到最終狀態(tài)的值,傳入相同的處理函數(shù),不論是成功還是失敗都能直接拋出到最外層
resolvePromise(promise2, y, resolve, reject)
},
(r) => {
if (called) return
called = true
// 如果傳入的 Promise 被拒絕,直接拋出到最外層
reject(r)
}
)
} else {
// 不是 Promise 對(duì)象,當(dāng)做普通值處理
resolve(x)
}
} catch (e) {
// 如果中間有錯(cuò)誤。直接變?yōu)榫芙^態(tài)
// 但是如果出現(xiàn)錯(cuò)誤之前已經(jīng)改變了狀態(tài),那么久不用管
if (called) return
called = true
reject(e)
}
} else {
// 普通值處理
resolve(x)
}
}
可以將上面的處理過(guò)程的代碼實(shí)現(xiàn)與描述一步步帶入查看,基本上都是能吻合的。
下面將其帶入到then中:
class MyPromise<T> {
// ...
public then<TResult1 = T, TResult2 = never>(
onfulfilled?: onFulfilled<T, TResult1>,
onrejected?: onRejected<TResult2>
): MyPromise<TResult1 | TResult2> {
// 現(xiàn)在我們將這個(gè)新生成的 Promise 和現(xiàn)在的 Promise 相互聯(lián)系
const promise2 = new MyPromise<TResult1 | TResult2>((resolve, reject) => {
if (this.status === Status.FULFILLED) {
setTimeout(() => {
try {
// 獲取到 x,然后與要返回的 Promise 產(chǎn)生聯(lián)系
let x = onfulfilled!(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
}
if (this.status === Status.REJECTED) {
setTimeout(() => {
try {
// 獲取到 x,然后與要返回的 Promise 產(chǎn)生聯(lián)系
let x = onrejected!(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
}
if (this.status === Status.PENDING) {
// 如果為 pending,需要將 onFulfilled 和 onRejected 函數(shù)都存放起來(lái),狀態(tài)確定后再依次執(zhí)行
// 執(zhí)行回調(diào)的時(shí)候有 setTimeout,這里就不加了
this.onFulfilledCallback.push(() => {
try {
let x = onfulfilled!(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
this.onRejectedCallback.push(() => {
try {
let x = onrejected!(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
}
})
return promise2
}
//...
}
測(cè)試一下:
new MyPromise<void>((resolve) => {
resolve()
})
.then(() => {
return 'step1'
})
.then((res) => {
return res + ':' + 'step2'
})
.then((res) => {
console.log(res) // step1:step2
})
很好,完美符合預(yù)期。
值的穿透
之前我們使用then時(shí)都是假設(shè)我們一定會(huì)向then中傳入回調(diào)函數(shù),但是事實(shí)上在 Promise/A+ 規(guī)范中兩個(gè)回調(diào)函數(shù)都是可以缺省的,這也是為什么我會(huì)在后面加上?。當(dāng)我們不向其傳入回調(diào)函數(shù)時(shí),此時(shí)就會(huì)觸發(fā)值的穿透效果。
// 就像下面這樣
new Promise((reslove) => {
reslove('hello')
})
.then()
.then()
.then()
.then((res) => {
console.log(res) // 'hello'
})
所以我們需要改造一下我們的then函數(shù),改造方法其實(shí)非常簡(jiǎn)單:
class MyPromise<T> {
// ...
public then<TResult1 = T, TResult2 = never>(
onfulfilled?: onFulfilled<T, TResult1>,
onrejected?: onRejected<TResult2>
): MyPromise<TResult1 | TResult2> {
// 如果傳入的不是函數(shù),就進(jìn)行值的穿透,成功回調(diào)是返回相同的值,失敗的回調(diào)是直接拋出錯(cuò)誤
// 注意這里不能直接給上面?zhèn)魅氲膮?shù)添加默認(rèn)值,因?yàn)樾枰袛嗍欠袷呛瘮?shù)
const onfulfilledFn =
typeof onfulfilled === 'function'
? onfulfilled
: (v: T | TResult1) => v as TResult1
const onrejectedFn =
typeof onrejected === 'function'
? onrejected
: (e: any) => {
throw e
}
// 將下面的 onfulfilled 改成 onfulfilledFn,onrejected 改成 onrejectedFn 就行了
// 現(xiàn)在我們將這個(gè)新生成的 Promise 和現(xiàn)在的 Promise 相互聯(lián)系
const promise2 = new MyPromise<TResult1 | TResult2>((resolve, reject) => {
if (this.status === Status.FULFILLED) {
setTimeout(() => {
try {
// 獲取到 x,然后與要返回的 Promise 產(chǎn)生聯(lián)系
let x = onfulfilledFn(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
}
if (this.status === Status.REJECTED) {
setTimeout(() => {
try {
// 獲取到 x,然后與要返回的 Promise 產(chǎn)生聯(lián)系
let x = onrejectedFn(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
}
if (this.status === Status.PENDING) {
// 如果為 pending,需要將 onFulfilled 和 onRejected 函數(shù)都存放起來(lái),狀態(tài)確定后再依次執(zhí)行
// 執(zhí)行回調(diào)的時(shí)候有 setTimeout,這里就不加了
this.onFulfilledCallback.push(() => {
try {
let x = onfulfilledFn(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
this.onRejectedCallback.push(() => {
try {
let x = onrejectedFn(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
}
})
return promise2
}
//...
}
好了,看到了這里,恭喜你,已經(jīng)完成了 Promise 最重要的部分,后續(xù)的所有 api 基本都是圍繞著上面所寫的部分展開的。
規(guī)范測(cè)試
使用我們前面提到的測(cè)試 Promise 規(guī)范的第三方庫(kù)來(lái)進(jìn)行測(cè)試:
npm install -D
# or
yarn add promises-aplus-tests -D
// 在文件末尾加上
// 忽略 typescript 校驗(yàn)
// @ts-ignore
MyPromise.defer = MyPromise.deferred = function () {
let dfd: any = {}
dfd.promise = new MyPromise((resolve, reject) => {
dfd.resolve = resolve
dfd.reject = reject
})
return dfd
}
export = MyPromise
然后使用tsc命令將ts文件編譯,運(yùn)行npx promises-aplus-tests 編譯后的js文件位置。

遺憾的是,我們的 Promise 并沒(méi)有通過(guò)所有的測(cè)試,但是我們可以看到這 16 個(gè)未通過(guò)測(cè)試的報(bào)錯(cuò)都相同,調(diào)用處理的回調(diào)超時(shí)(超過(guò)了 200 ms 的延時(shí)),我的個(gè)人理解是由于setTimeout這個(gè) api 不能完全模擬微任務(wù)而造成的延時(shí)效果(說(shuō)錯(cuò)了請(qǐng)大佬們輕點(diǎn)噴)。
如果要單看測(cè)試結(jié)果來(lái)說(shuō),想全部通過(guò)測(cè)試我們可以把最開始定義的 Promise 內(nèi)部的reslove函數(shù)做一個(gè)修改:
class MyPromise{
private _resolve(value: T | PromiseLike<T>) {
try{
setTimeout(() => {
/*
刪除下面這段代碼就可通過(guò)全部測(cè)試:
if (isPromise(value)) {
value.then(this._resolve.bind(this), this._reject.bind(this))
return
}
*/
if (this.status === Status.PENDING) {
this.status = Status.FULFILLED
this.value = value as T // 強(qiáng)制轉(zhuǎn)換類型
this.onFulfilledCallback.forEach((fn) => fn())
}
})
}catch(err){
this._reject(err)
}
}
}
當(dāng)然,雖然通過(guò)了全部測(cè)試,但是很明顯并不是符合預(yù)期的結(jié)果,當(dāng)我們使用一個(gè)PromiseLike對(duì)象時(shí)與真實(shí)的 Promise 結(jié)果并不一致:
// 還是用最開始的那個(gè)例子
new Promise((resolve) => {
resolve({
prop: 'common property',
then(reslove2: any) {
reslove2('promiselike')
}
})
}).then((res) => {
// 真實(shí)的 Promise 這里是 promiselike
console.log(res) // { prop: 'common property', then: [Function: then] }
})
所以,就結(jié)果而言,也算是基本合格吧。
Promise 的拓展方法
在前面我們已經(jīng)完成了 Promise 的核心部分,現(xiàn)在可以依靠之前的代碼再次完善我們的 Promise。
注:在 Promise 的接口定義里,所有的實(shí)例方法都是定義在Promise<T>接口中的,所有的靜態(tài)方法都是定義在PromiseConstructor接口中的。
Promise.prototype.catch
Promise.prototype.catch(onrejected) 方法返回一個(gè)Promise,并且處理拒絕的情況。它的行為與調(diào)用Promise.prototype.then(undefined, onRejected)相同。
接口類型:
interface Promise<T> {
/**
* Attaches a callback for only the rejection of the Promise.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of the callback.
*/
catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<T | TResult>;
}
實(shí)現(xiàn)代碼:
interface MyPromise {
// 事實(shí)上它內(nèi)部就是這樣調(diào)用的
public catch<TResult = never>(
onrejected?: onRejected<TResult>
): MyPromise<T | TResult> {
return this.then(null, onrejected)
}
}
Promise.resolve
Promise.resolve(value)方法返回一個(gè)以給定值解析后的 Promise 對(duì)象。
- 如果這個(gè)值是一個(gè) Promise 實(shí)例 ,那么將返回這個(gè) Promise 實(shí)例。
- 如果這個(gè)值是
thenable,會(huì)一直跟隨thenable拿到它的最終狀態(tài)。 - 如果都不是上面的值,返回的 Promise 實(shí)例將用這個(gè)值作為成功狀態(tài)的終值。
接口類型:
interface PromiseConstructor {
// 可以看到有兩種函數(shù)體,所以我們需要進(jìn)行函數(shù)重載的定義
/**
* Creates a new resolved promise.
* @returns A resolved promise.
*/
resolve(): Promise<void>;
/**
* Creates a new resolved promise for the provided value.
* @param value A promise.
* @returns A promise whose internal state matches the provided promise.
*/
resolve<T>(value: T | PromiseLike<T>): Promise<T>;
}
實(shí)現(xiàn)代碼:
interface MyPromise {
// 函數(shù)重載
static resolve(): MyPromise<void>
static resolve<T>(value: T | PromiseLike<T>): MyPromise<T>
// 最后的函數(shù)實(shí)體需要同時(shí)支持上面兩種函數(shù)重載的類型,所以我們變成可選值
static resolve<T>(value?: T | PromiseLike<T>): MyPromise<T> {
// 如果是 Promise,直接返回當(dāng)前 Promise
if (value instanceof MyPromise) {
return value
}
return new MyPromise((resolve) => {
// 我們?cè)趦?nèi)部已經(jīng)做了對(duì) thenable 的處理了,所以直接 reslove
// 因?yàn)楸仨殏髦担赃@里就強(qiáng)制推斷了
resolve(value!)
})
}
}
Promise.reject
Promise.reject(reason)方法返回一個(gè)帶有拒絕原因的Promise對(duì)象。
接口類型:
interface PromiseConstructor {
/**
* Creates a new rejected promise for the provided reason.
* @param reason The reason the promise was rejected.
* @returns A new rejected Promise.
*/
reject<T = never>(reason?: any): Promise<T>;
}
實(shí)現(xiàn)代碼:
interface MyPromise {
static reject<T = never>(reason?: any): MyPromise<T> {
// 不需要額外判斷
return new MyPromise((resolve, reject) => {
reject(reason)
})
}
}
Promise.all
Promise.all(iterable)方法接收一個(gè)iterable對(duì)象,返回一個(gè) Promise 實(shí)例,此實(shí)例在 iterable 參數(shù)內(nèi)所有的 thenable 狀態(tài)都為fulfilled或參數(shù)中不包含 thenable 時(shí)狀態(tài)為fulfilled,并且reslove一個(gè)包含了所有傳入thenable的reslove值的數(shù)組。如果參數(shù)內(nèi)的 thenable 有一個(gè)狀態(tài)為rejected,此實(shí)例狀態(tài)也為rejected,并且reject第一個(gè)失敗 thenable 的結(jié)果。否者如果有thenable的狀態(tài)為pending,此實(shí)例的狀態(tài)也為pending。
接口定義:
interface PromiseConstructor {
/**
* Creates a Promise that is resolved with an array of results when all of the provided Promises
* resolve, or rejected when any Promise is rejected.
* @param values An array of Promises.
* @returns A new Promise.
*/
all<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>, T9 | PromiseLike<T9>, T10 | PromiseLike<T10>]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]>;
all<T1, T2, T3, T4, T5, T6, T7, T8, T9>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>, T9 | PromiseLike<T9>]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9]>;
all<T1, T2, T3, T4, T5, T6, T7, T8>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8]>;
all<T1, T2, T3, T4, T5, T6, T7>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>]): Promise<[T1, T2, T3, T4, T5, T6, T7]>;
all<T1, T2, T3, T4, T5, T6>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>]): Promise<[T1, T2, T3, T4, T5, T6]>;
all<T1, T2, T3, T4, T5>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>]): Promise<[T1, T2, T3, T4, T5]>;
all<T1, T2, T3, T4>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>]): Promise<[T1, T2, T3, T4]>;
all<T1, T2, T3>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>]): Promise<[T1, T2, T3]>;
all<T1, T2>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>]): Promise<[T1, T2]>;
all<T>(values: readonly (T | PromiseLike<T>)[]): Promise<T[]>;
// 看著有點(diǎn)多,其實(shí)上面都是表示傳入?yún)?shù)是一個(gè)數(shù)組的情況,這樣寫是因?yàn)閭魅氲?Promise<T> 中的 T 可能不同而重載不同元組類型
// see: lib.es2015.iterable.d.ts
all<T>(values: Iterable<T | PromiseLike<T>>): Promise<T[]>;
}
在類型定義中我們可以看到,當(dāng)我們傳入給Promise.all()一個(gè)迭代器(Iterable)的時(shí)候參數(shù)也是正確的,而數(shù)組本質(zhì)也是一個(gè)迭代器,所以我們的編碼操作可以完全圍繞著迭代器進(jìn)行展開。
實(shí)現(xiàn)代碼:
interface MyPromise {
static all<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(
values: readonly [
T1 | PromiseLike<T1>,
T2 | PromiseLike<T2>,
T3 | PromiseLike<T3>,
T4 | PromiseLike<T4>,
T5 | PromiseLike<T5>,
T6 | PromiseLike<T6>,
T7 | PromiseLike<T7>,
T8 | PromiseLike<T8>,
T9 | PromiseLike<T9>,
T10 | PromiseLike<T10>
]
): MyPromise<[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]>
// .....太占篇幅,省略了
static all<T>(values: Iterable<T | PromiseLike<T>>): MyPromise<T[]>
// 我們這里的實(shí)際實(shí)現(xiàn)也完全按照按照迭代器來(lái)實(shí)現(xiàn)就行了
static all<T>(values: Iterable<T | PromiseLike<T>>): MyPromise<T[]> {
return new MyPromise((resolve, reject) => {
// PromiseLike<T> 對(duì)象會(huì)跟蹤轉(zhuǎn)換為 T
const resultArr: T[] = []
// 判斷是否已經(jīng)全部完成了
const doneArr: boolean[] = []
// 獲取迭代器對(duì)象
let iter = values[Symbol.iterator]()
// 獲取值 {value:xxx, done: false}
let cur = iter.next()
// 判斷迭代器是否迭代完畢同時(shí)將最后得到的值放入結(jié)果數(shù)組中
const resolveResult = (value: T, index: number, done?: boolean) => {
resultArr[index] = value
doneArr[index] = true
if (done && doneArr.every((item) => item)) {
resolve(resultArr)
}
}
for (let i = 0; !cur.done; i++) {
const value = cur.value
doneArr.push(false)
cur = iter.next()
if (isPromise(value)) {
value.then((value: T) => {
resolveResult(value, i, cur.done)
}, reject)
} else {
resolveResult(value, i, cur.done)
}
}
})
}
Promise.race
Promise.race(iterable) 方法接收一個(gè)iterable對(duì)象,返回一個(gè) Promise,一旦迭代器中的某個(gè)thenable的狀態(tài)變?yōu)?code>fulfiled或rejected,該實(shí)例的狀態(tài)就會(huì)變成fulfiled或rejected。
接口定義:
interface PromiseConstructor {
/**
* Creates a Promise that is resolved or rejected when any of the provided Promises are resolved
* or rejected.
* @param values An array of Promises.
* @returns A new Promise.
*/
race<T>(values: readonly T[]): Promise<T extends PromiseLike<infer U> ? U : T>;
// see: lib.es2015.iterable.d.ts
race<T>(values: Iterable<T>): Promise<T extends PromiseLike<infer U> ? U : T>;
}
代碼實(shí)現(xiàn):
class MyPromise {
static race<T>(
values: Iterable<T>
): MyPromise<T extends PromiseLike<infer U> ? U : T>
static race<T>(
values: readonly T[]
): MyPromise<T extends PromiseLike<infer U> ? U : T>
// 還是直接使用迭代器
static race<T>(
values: Iterable<T>
): MyPromise<T extends PromiseLike<infer U> ? U : T> {
return new MyPromise((resolve, reject) => {
const iter = values[Symbol.iterator]()
let cur = iter.next()
while (!cur.done) {
const value = cur.value
cur = iter.next()
if (isPromise(value)) {
value.then(resolve, reject)
} else {
// 普通值,這時(shí)的值為 T,但是 Typescript 無(wú)法再深度判斷了,需要自己手動(dòng)轉(zhuǎn)換
resolve(value as T extends PromiseLike<infer U> ? U : T)
}
}
})
}
}
Promise.prototype.finally
ES2018提出
Promise.prototype.finally(onfinally) 方法返回一個(gè)新的 Promise,并且該 Promise 的狀態(tài)為 Promise 鏈條中前一個(gè) Promise 的狀態(tài)。在上一個(gè) Promise 結(jié)束時(shí),無(wú)論結(jié)果狀態(tài)是fulfilled或者是rejected,都會(huì)執(zhí)行指定的回調(diào)函數(shù)。這為在Promise是否成功完成后都需要執(zhí)行的代碼提供了一種方式。避免了同樣的語(yǔ)句需要在then()和catch()中各寫一次的情況。
具體用法:
// 不使用 finally
new Promise((resolve) => {
resolve()
}).then(() => {
console.log('success')
console.log('finally')
})
.catch(() => {
console.log('error')
console.log('finally')
})
// 使用 finally
new Promise((resolve) => {
resolve()
}).then(() => {
console.log('success')
})
.catch(() => {
console.log('error')
})
.finally(() => {
console.log('finally')
})
接口定義:
interface Promise<T> {
/**
* Attaches a callback that is invoked when the Promise is settled (fulfilled or rejected). The
* resolved value cannot be modified from the callback.
* @param onfinally The callback to execute when the Promise is settled (fulfilled or rejected).
* @returns A Promise for the completion of the callback.
*/
finally(onfinally?: (() => void) | undefined | null): Promise<T>
}
代碼實(shí)現(xiàn):
class MyPromise {
// 無(wú)論如何都會(huì)執(zhí)行
public finally(onfinally?: onFinally): MyPromise<T> {
return this.then(
(value) =>
MyPromise.resolve(
// 如果 onfinally 返回的是一個(gè) thenable 也會(huì)等返回的 thenable 狀態(tài)改變才會(huì)進(jìn)行后續(xù)的 Promise
typeof onfinally === 'function' ? onfinally() : onfinally
).then(() => value),
(reason) =>
MyPromise.resolve(
typeof onfinally === 'function' ? onfinally() : onfinally
).then(() => {
throw reason
})
)
}
}
Promise.allSettled
ES2020提出
Promise.allSettled(iterable)方法接收一個(gè)iterable對(duì)象,返回一個(gè) Promise 實(shí)例,該實(shí)例的狀態(tài)總是fulfilled或pending。在 iterable 參數(shù)內(nèi)所有的 thenable 狀態(tài)不論為fullfilled還是rejected,reslove或reject的值都會(huì)被包裝成一個(gè)對(duì)象保留,當(dāng)所有的thenable執(zhí)行完畢后該 Promise 實(shí)例會(huì)reslove一個(gè)包含了這些所有對(duì)象的數(shù)組。如果有thenable的狀態(tài)為pending,此實(shí)例的狀態(tài)也為pending。
具體用法:
const promise1 = new Promise((resolve) => {
resolve(1)
})
const promise2 = new Promise((resolve) => {
resolve(2)
})
const promise3 = new Promise((resolve, reject) => {
reject(3)
})
Promise.allSettled([promise1, promise2, promise3]).then(console.log)
/*
打印結(jié)果為:
[
{ status: 'fulfilled', value: 1 },
{ status: 'fulfilled', value: 2 },
{ status: 'rejected', reason: 3 }
]
*/
接口定義:
interface PromiseConstructor {
/**
* Creates a Promise that is resolved with an array of results when all
* of the provided Promises resolve or reject.
* @param values An array of Promises.
* @returns A new Promise.
*/
allSettled<T extends readonly unknown[] | readonly [unknown]>(values: T):
Promise<{ -readonly [P in keyof T]: PromiseSettledResult<T[P] extends PromiseLike<infer U> ? U : T[P]> }>;
/**
* Creates a Promise that is resolved with an array of results when all
* of the provided Promises resolve or reject.
* @param values An array of Promises.
* @returns A new Promise.
*/
allSettled<T>(values: Iterable<T>): Promise<PromiseSettledResult<T extends PromiseLike<infer U> ? U : T>[]>;
}
代碼實(shí)現(xiàn):
class MyPromise<T> {
static allSettled<T extends readonly unknown[] | readonly [unknown]>(
values: T
): MyPromise<
{
-readonly [P in keyof T]: PromiseSettledResult<
T[P] extends PromiseLike<infer U> ? U : T[P]
>
}
>
static allSettled<T>(
values: Iterable<T>
): MyPromise<PromiseSettledResult<T extends PromiseLike<infer U> ? U : T>[]>
// 重載函數(shù)的返回值有沖突,想不報(bào)錯(cuò)需要使用聯(lián)合類型,這邊圖省事直接用 any 了
static allSettled<T>(values: Iterable<T>): MyPromise<any> {
// 大體寫法參照 Promise.all()
return new MyPromise((reslove) => {
const resultArr: any[] = []
const doneArr: boolean[] = []
// 獲取迭代器
const iter = values[Symbol.iterator]()
// 當(dāng)前值
let cur = iter.next()
const resolveResult = (value: any, index: number, done?: boolean) => {
resultArr[index] = {
status: Status.FULFILLED,
value
}
doneArr[index] = true
if (done && doneArr.every((item) => item)) {
reslove(resultArr)
}
}
for (let i = 0; !cur.done; i++) {
const value = cur.value
doneArr.push(false)
cur = iter.next()
if (isPromise(value)) {
value.then(
(value) => {
resolveResult(value, i, cur.done)
},
(reason) => {
// 這里和 resolve 基本也沒(méi)什么區(qū)別,修改一下?tīng)顟B(tài)和屬性就ok了
resultArr[i] = {
status: Status.REJECTED,
reason
}
doneArr[i] = true
if (cur.done && doneArr.every((item) => item)) {
reslove(resultArr)
}
}
)
// 不是 thenable 直接存儲(chǔ)
} else {
resolveResult(value, i, cur.done)
}
}
})
}
}
Promise.any
ESNEXT提出,還處于實(shí)驗(yàn)版本,只有少部分瀏覽器支持
Promise.any(iterable)方法接收一個(gè) iterable 對(duì)象,返回一個(gè) Promise 實(shí)例。只要iterable中的一個(gè) thenable 的狀態(tài)為fulfilled,就返回那個(gè)thenable所reslove的值,并且該實(shí)例的狀態(tài)也為fulfilled。如果iterable中全為thenable并且狀態(tài)全部為rejected,該實(shí)例的狀態(tài)也為rejected并且reject一個(gè)AggregateError類型的實(shí)例(它是 Error 的一個(gè)子類,用于把單一的錯(cuò)誤集合在一起,目前還在實(shí)驗(yàn)階段,只有少部分瀏覽器支持)。本質(zhì)上,這個(gè)方法和Promise.all()是相反的。
具體用法:
const pErr = new Promise((resolve, reject) => {
reject("總是失敗");
});
const pSlow = new Promise((resolve, reject) => {
setTimeout(resolve, 500, "最終完成");
});
const pFast = new Promise((resolve, reject) => {
setTimeout(resolve, 100, "很快完成");
});
Promise.any([pErr, pSlow, pFast]).then((value) => {
console.log(value);
// pFast fulfils first
})
// 打印結(jié)果為: "很快完成"
接口定義:
interface PromiseConstructor {
/**
* The any function returns a promise that is fulfilled by the first given promise to be fulfilled, or rejected with an AggregateError containing an array of rejection reasons if all of the given promises are rejected. It resolves all elements of the passed iterable to promises as it runs this algorithm.
* @param values An array or iterable of Promises.
* @returns A new Promise.
*/
any<T>(values: (T | PromiseLike<T>)[] | Iterable<T | PromiseLike<T>>): Promise<T>
}
代碼實(shí)現(xiàn):
class MyPromise<T> {
static any<T>(
values: (T | PromiseLike<T>)[] | Iterable<T | PromiseLike<T>>
): MyPromise<T> {
return new MyPromise((resolve, reject) => {
// 接收迭代器
const iter = values[Symbol.iterator]()
let cur = iter.next()
const doneArr: boolean[] = []
for (let i = 0; !cur.done; i++) {
const value = cur.value
cur = iter.next()
doneArr.push(false)
if (isPromise(value)) {
// 如果為 thenable,根據(jù)該 thenable 的狀態(tài)進(jìn)行判斷
value.then(resolve, () => {
doneArr[i] = true
// 只有傳入迭代器的值全是 thenable 并且 thenable 的狀態(tài)全部為 rejected 才會(huì)觸發(fā)
if (cur.done && doneArr.every((item) => item)) {
// 應(yīng)該拋出 AggregateError 的錯(cuò)誤類型,但是因?yàn)?AggregateError 因?yàn)槭菍?shí)驗(yàn)版本,所有只有最新版瀏覽器才會(huì)有,我這里就用 Error 代替了
const e = new Error('All promises were rejected')
e.stack = ''
reject(e)
}
})
} else {
resolve(value)
}
}
})
}
}
總結(jié)
本文使用 typescript,根據(jù)類型定義從零開始實(shí)現(xiàn)了一個(gè) Promise,其中重點(diǎn)深入了對(duì)于then方法的處理。雖不完美,但也算達(dá)到了想要的效果。作者技術(shù)有限,如果有什么錯(cuò)誤或遺漏的地方還請(qǐng)?jiān)谠u(píng)論區(qū)中指出,順便求個(gè)??。
文章的代碼已上傳至 github