俗話說站在前輩巨擘的肩上,才能尿的更遠。做爲一個頂風尿三丈的小人物,在拜讀了巨擘大咖們寫的promise實現以後,全身經絡通暢,如被先輩們用金手指點中了百會穴。至此之後,運行大小週天比往常更熟練了幾分。然而,肩井穴,涌泉穴,每日亥時,都會隱隱做痛。思來想去,大概時先前巨擘的文章精妙,我一時沒法所有領悟其中奧妙。固苦心感悟,方得此篇。不敢與前輩比肩,只當部分補充而已es6
這裏咱們用es6來實現,這樣結構比較明顯,若是有對es6不太熟悉的朋友,能夠看看阮一峯老師的ECMAScript 6 入門web
class myPromise {
constructor(executor){ this.value = null; this.reason = null; const resolve = value =>{ this.value = value; } const reject = reason => { this.reason = reason; } try { executor(resolve,reject) } catch (e) { reject(e) } } then(onFulfilled,onRejected){ onFulfilled(this.value) onRejected(this.reason) } } 複製代碼
代碼解析:npm
觀察後發現:咱們實現的myPormise和Promise運行的結果一致(good guy!),只是有一個小問題,咱們是先調用的p1的then,可是p1的then返回倒是在p2的then返回以後。咱們保留疑問,繼續淦!!!json
意思就是當一個promise中的resolve或者reject執行了以後,那以後resolve/reject都再也不執行數組
觀察以後,發現這就不對了promise
因此...(就決定是你了,皮卡丘!!!)異步
class myPromise {
constructor(executor){ + this.state = 'pending'; //內部狀態爲pending,resolve,reject this.value = null; this.reason = null; const resolve = value => { + if(this.state === 'pending'){ + this.state = 'fulfilled'; this.value = value; + } } const reject = reason => { + if(this.state === 'pending'){ + this.state = 'rejected'; this.reason = reason; + } } try { executor(resolve,reject) } catch (e) { reject(e) } } then(onFulfilled,onRejected){ + if(this.state === 'fulfilled'){ onFulfilled(this.value) + } + if(this.state === 'rejected') { onRejected(this.reason) + } } } 複製代碼
修改以後,再觀察,我們家的promise又正常了一些。編輯器
咱們稍微清理一下咱們的測試代碼,使它看上去清爽天然函數
清理完以後。咱們加上異步測試
經過觀察,咱們發現,咱們的promise沒有任何打印
基於上面所說,咱們修改咱們的promise
class myPromise {
constructor(executor){ this.state = 'pending'; //內部狀態爲pending,resolve,reject this.value = null; this.reason = null; + this.onFulfilledCallbacks = []; + this.onRejectedCallbacks = []; const resolve = value =>{ if(this.state === 'pending'){ this.state = 'fulfilled'; this.value = value; + this.onFulfilledCallbacks.forEach(fn=>fn(value)) } } const reject = reason => { if(this.state === 'pending'){ this.state = 'rejected'; this.reason = reason; + this.onRejectedCallbacks.forEach(fn=>fn(reason)) } } try { executor(resolve,reject) } catch (e) { reject(e) } } then(onFulfilled,onRejected){ if(this.state === 'fulfilled'){ onFulfilled(this.value) } if(this.state === 'rejected') { onRejected(this.reason) } + if(this.state === 'pending') { + this.onFulfilledCallbacks.push(onFulfilled) + this.onRejectedCallbacks.push(onRejected) + } } } 複製代碼
修改以後,咱們看看結果 觀察以後,發現咱們的promise可以正常的顯示then回調了,並且還有意外收穫,仔細觀察咱們發現,p1.then和p2.then打印的順序和調用時的順序一致了!!!
不論promise裏面的resolve/reject是同步或者異步,咱們都但願then返回的執行表現一致 咱們建立一個執行對比
通過觀察,咱們能夠發現
那麼怎麼改呢?咱們的目的是要保持then的執行一致,因此只能把所有的then修改爲異步的,緣由在上一節已經說明了 咱們來修改一下我們家的promise
class myPromise {
constructor(executor) { this.state = 'pending'; //內部狀態爲pending,resolve,reject this.value = null; this.reason = null; this.onFulfilledCallbacks = []; this.onRejectedCallbacks = []; const resolve = value => { if (this.state === 'pending') { this.state = 'fulfilled'; this.value = value; this.onFulfilledCallbacks.forEach(fn => fn(value)) } } const reject = reason => { if (this.state === 'pending') { this.state = 'rejected'; this.reason = reason; this.onRejectedCallbacks.forEach(fn => fn(reason)) } } try { executor(resolve, reject) } catch (e) { reject(e) } } then(onFulfilled, onRejected) { if (this.state === 'fulfilled') { + setTimeout(()=>{ onFulfilled(this.value) + }) } if (this.state === 'rejected') { + setTimeout(()=>{ onRejected(this.reason) + }) } if (this.state === 'pending') { + this.onFulfilledCallbacks.push((value)=>setTimeout(()=>{onFulfilled(value)})) + this.onRejectedCallbacks.push((reason)=>setTimeout(()=>{onRejected(reason)})) } } } 複製代碼
而後來看看執行
如今我們家的promise就更像別人家的了
細心的小夥伴會發現this.onFulfilledCallbacks和this.onRejectedCallbacks是數組,在then方法裏面,當state === 'pending'時,咱們把onFulfilled和onRejected添加再數組進數組,而不是直接賦值給this.onFulfilledCallbacks/this.onRejectedCallbacks。會以爲這裏直接賦值好像也沒有什麼問題。
咱們修改一下咱們promise直接用變量存儲
class myPromise {
constructor(executor) { this.state = "pending"; //內部狀態爲pending,resolve,reject this.value = null; this.reason = null; this.onFulfilledCallbacks = []; this.onRejectedCallbacks = []; const resolve = (value) => { if (this.state === "pending") { this.state = "fulfilled"; this.value = value; - this.onFulfilledCallbacks.forEach((fn) => fn(value)); + this.onFulfilledCallbacks(value); } }; const reject = (reason) => { if (this.state === "pending") { this.state = "rejected"; this.reason = reason; this.onRejectedCallbacks.forEach((fn) => fn(reason)); } }; try { executor(resolve, reject); } catch (e) { reject(e); } } then(onFulfilled, onRejected) { if (this.state === "fulfilled") { setTimeout(() => { onFulfilled(this.value) }) } if (this.state === "rejected") { setTimeout(() => { onRejected(this.reason) }) } if (this.state === "pending") { - this.onFulfilledCallbacks.push((value)=>setTimeout(()=>{onFulfilled(value)})); + this.onFulfilledCallbacks = (value)=>setTimeout(()=>{onFulfilled(value)}); this.onRejectedCallbacks.push(onRejected); } } } 複製代碼
通過觀察咱們發現:
咱們把代碼回滾到上一節,而後進入下一節
then方法不管什麼時候都返回一個promise實例
咱們仔細觀察一下
咱們按着咱們的分析來修改一下咱們的promise
class myPromise {
constructor(executor) { this.state = "pending"; //內部狀態爲pending,resolve,reject this.value = null; this.reason = null; this.onFulfilledCallbacks = []; this.onRejectedCallbacks = []; const resolve = (value) => { if (this.state === "pending") { this.state = "fulfilled"; this.value = value; this.onFulfilledCallbacks.forEach((fn) => fn(value)); } }; const reject = (reason) => { if (this.state === "pending") { this.state = "rejected"; this.reason = reason; this.onRejectedCallbacks.forEach((fn) => fn(reason)); } }; try { executor(resolve, reject); } catch (e) { reject(e); } } then(onFulfilled, onRejected) { if (this.state === "fulfilled") { setTimeout(() => { onFulfilled(this.value) }) } if (this.state === "rejected") { setTimeout(() => { onRejected(this.reason) }) } if (this.state === "pending") { this.onFulfilledCallbacks.push((value)=>setTimeout(()=>{onFulfilled(value)})); this.onFulfilledCallbacks = (value)=>setTimeout(()=>{onFulfilled(value)}); } + return new myPromise((resolve,reject)=>{ + resolve() + }) } } 複製代碼
修改完成以後,咱們執行看看
通過觀察咱們能夠發現
第二個then的onFulfilled的參數是第一個onFuifilled的return值
因此咱們修改一下咱們執行代碼
這裏有一個小tips,這裏用了並的邏輯運算符,console.log()這個函數返回一個undefined,因此在前面取了非
花開兩朵各表一枝,
咱們觀察發現
咱們按着這個思路,來改改我們家的promise
class myPromise {
constructor(executor) { this.state = "pending"; //內部狀態爲pending,resolve,reject this.value = null; this.reason = null; this.onFulfilledCallbacks = []; this.onRejectedCallbacks = []; const resolve = (value) => { if (this.state === "pending") { this.state = "fulfilled"; this.value = value; this.onFulfilledCallbacks.forEach((fn) => fn(value)); } }; const reject = (reason) => { if (this.state === "pending") { this.state = "rejected"; this.reason = reason; this.onRejectedCallbacks.forEach((fn) => fn(reason)); } }; try { executor(resolve, reject); } catch (e) { reject(e); } } then(onFulfilled, onRejected) { const promise2 = new myPromise((resolve, reject) => { if (this.state === "fulfilled") { setTimeout(() => { + // 萬一onFulfilled方法報錯,咱們用trycatch捕獲一下 + try { + let x = onFulfilled(this.value); + resolve(x) + } catch (error) { + reject(error) + } }) } if (this.state === "rejected") { setTimeout(() => { + try { + let x = onRejected(this.reason); + //這裏暫時有點問題,咱們先這麼寫,由於這裏比較符合邏輯 + reject(x) + } catch (error) { + reject(error) + } }) } if (this.state === "pending") { this.onFulfilledCallbacks.push(value => { + try { + let x = onFulfilled(value) + resolve(x) + } catch (error) { + reject(error) + } }); this.onRejectedCallbacks.push(reason => { + try { + let x = onRejected(reason) + //這裏暫時有點問題,咱們先這麼寫,由於這裏比較符合邏輯 + reject(x) + } catch (error) { + reject(error) + } }); } }) return promise2; } } 複製代碼
最後來看看結果
觀察能夠返現,我們家的promise已經和別人家的promise已經愈來愈像了(牛頭人警告!)
咱們來看看例子
仔細觀察咱們發現
我畫了一個圖
因此咱們來修改我們家的promise
class myPromise {
constructor(executor) { this.state = "pending"; //內部狀態爲pending,resolve,reject this.value = null; this.reason = null; this.onFulfilledCallbacks = []; this.onRejectedCallbacks = []; const resolve = (value) => { if (this.state === "pending") { this.state = "fulfilled"; this.value = value; this.onFulfilledCallbacks.forEach((fn) => fn(value)); } }; const reject = (reason) => { if (this.state === "pending") { this.state = "rejected"; this.reason = reason; this.onRejectedCallbacks.forEach((fn) => fn(reason)); } }; try { executor(resolve, reject); } catch (e) { reject(e); } } then(onFulfilled, onRejected) { const promise2 = new myPromise((resolve, reject) => { if (this.state === "fulfilled") { setTimeout(() => { // 萬一onFulfilled方法報錯,咱們用trycatch捕獲一下 try { let x = onFulfilled(this.value); resolve(x) } catch (error) { reject(error) } }) } if (this.state === "rejected") { setTimeout(() => { try { let x = onRejected(this.reason); - //這裏暫時有點問題,咱們先這麼寫,由於這裏比較符合邏輯 - reject(x) + resolve(x) } catch (error) { reject(error) } }) } if (this.state === "pending") { this.onFulfilledCallbacks.push(value => { try { let x = onFulfilled(value) resolve(x) } catch (error) { reject(error) } }); this.onRejectedCallbacks.push(reason => { try { let x = onRejected(reason) - //這裏暫時有點問題,咱們先這麼寫,由於這裏比較符合邏輯 - reject(x) + reslove(x) } catch (error) { reject(error) } }); } }) return promise2; } } 複製代碼
修改完了,咱們來看看結果
bingo!!! 我們家的promise又像了別人家的promise幾分
大致上的 結構已經完成了,接下來咱們要調整一下,方便接下來的對比
class myPromise {
constructor(executor) { this.state = "pending"; //內部狀態爲pending,resolve,reject this.value = null; this.reason = null; this.onFulfilledCallbacks = []; this.onRejectedCallbacks = []; const resolve = (value) => { if (this.state === "pending") { this.state = "fulfilled"; this.value = value; this.onFulfilledCallbacks.forEach((fn) => fn(value)); } }; const reject = (reason) => { if (this.state === "pending") { this.state = "rejected"; this.reason = reason; this.onRejectedCallbacks.forEach((fn) => fn(reason)); } }; try { executor(resolve, reject); } catch (e) { reject(e); } } then(onFulfilled, onRejected) { const promise2 = new myPromise((resolve, reject) => { if (this.state === "fulfilled") { setTimeout(() => { // 萬一onFulfilled方法報錯,咱們用trycatch捕獲一下 try { let x = onFulfilled(this.value); - reslove(x) + resolvePromise(promise,x,resolve,reject) } catch (error) { reject(error) } }) } if (this.state === "rejected") { setTimeout(() => { try { let x = onRejected(this.reason); - reslove(x) + resolvePromise(promise,x,resolve,reject) } catch (error) { reject(error) } }) } if (this.state === "pending") { this.onFulfilledCallbacks.push(value => { try { let x = onFulfilled(value) - reslove(x) + resolvePromise(promise,x,resolve,reject) } catch (error) { reject(error) } }); this.onRejectedCallbacks.push(reason => { try { let x = onRejected(reason) - reslove(x) + resolvePromise(promise,x,resolve,reject) } catch (error) { reject(error) } }); } }) return promise2; } } + function resolvePromise(promise2,x,resovle,reject) { + resolve(x) + } 複製代碼
咱們建立了一個函數resolvePromise 專門來處理resolve相關的邏輯,由於這部分高度複用,因此咱們把它單獨抽離成一個函數,目前這個函數裏面仍是隻執行了resolve(x)
觀察能夠發現,
這裏我們要弄懂,promise鏈式調用,具體的實現邏輯
解析:
根據咱們的理解,來修改我們家的promise
class myPromise {
constructor(executor) { this.state = "pending"; //內部狀態爲pending,resolve,reject this.value = null; this.reason = null; this.onFulfilledCallbacks = []; this.onRejectedCallbacks = []; const resolve = (value) => { if (this.state === "pending") { this.state = "fulfilled"; this.value = value; this.onFulfilledCallbacks.forEach((fn) => fn(value)); } }; const reject = (reason) => { if (this.state === "pending") { this.state = "rejected"; this.reason = reason; this.onRejectedCallbacks.forEach((fn) => fn(reason)); } }; try { executor(resolve, reject); } catch (e) { reject(e); } } then(onFulfilled, onRejected) { const promise2 = new myPromise((resolve, reject) => { if (this.state === "fulfilled") { setTimeout(() => { // 萬一onFulfilled方法報錯,咱們用trycatch捕獲一下 try { let x = onFulfilled(this.value); resolvePromise(promise2, x, resolve, reject) } catch (error) { reject(error) } }) } if (this.state === "rejected") { setTimeout(() => { try { let x = onRejected(this.reason); resolvePromise(promise2, x, resolve, reject) } catch (error) { reject(error) } }) } if (this.state === "pending") { this.onFulfilledCallbacks.push(value => { try { let x = onFulfilled(value) resolvePromise(promise2, x, resolve, reject) } catch (error) { reject(error) } }); this.onRejectedCallbacks.push(reason => { try { let x = onRejected(reason) resolvePromise(promise2, x, resolve, reject) } catch (error) { reject(error) } }); } }) return promise2; } } function resolvePromise(promise2, x, resolve, reject) { + if (x instanceof myPromise) { + if (x.state === 'pending') { + x.then((y) => { + resolvePromise(promise2, y, resolve, reject) + }, reject) + } else { + x.then(resolve, reject) + } + } else { resolve(x) + } } 複製代碼
修改了以後,咱們來看看
觀察之後,發現我們家的promise也愈來愈標準化了
當resolve返回的是一個包含then函數的對象,或者函數時,要執行一次這個then函數
首先咱們來看看對比
通過觀察咱們能夠發現,
咱們按照咱們的想法來完善我們家的promise
class myPromise {
constructor(executor) { this.state = "pending"; //內部狀態爲pending,resolve,reject this.value = null; this.reason = null; this.onFulfilledCallbacks = []; this.onRejectedCallbacks = []; const resolve = (value) => { if (this.state === "pending") { this.state = "fulfilled"; this.value = value; this.onFulfilledCallbacks.forEach((fn) => fn(value)); } }; const reject = (reason) => { if (this.state === "pending") { this.state = "rejected"; this.reason = reason; this.onRejectedCallbacks.forEach((fn) => fn(reason)); } }; try { executor(resolve, reject); } catch (e) { reject(e); } } then(onFulfilled, onRejected) { const promise2 = new myPromise((resolve, reject) => { if (this.state === "fulfilled") { setTimeout(() => { // 萬一onFulfilled方法報錯,咱們用trycatch捕獲一下 try { let x = onFulfilled(this.value); resolvePromise(promise2, x, resolve, reject) } catch (error) { reject(error) } }) } if (this.state === "rejected") { setTimeout(() => { try { let x = onRejected(this.reason); resolvePromise(promise2, x, resolve, reject) } catch (error) { reject(error) } }) } if (this.state === "pending") { this.onFulfilledCallbacks.push(value => { try { let x = onFulfilled(value) resolvePromise(promise2, x, resolve, reject) } catch (error) { reject(error) } }); this.onRejectedCallbacks.push(reason => { try { let x = onRejected(reason) resolvePromise(promise2, x, resolve, reject) } catch (error) { reject(error) } }); } }) return promise2; } } function resolvePromise(promise2, x, resolve, reject) { if (x instanceof myPromise) { if (x.state === 'pending') { x.then((y) => { resolvePromise(promise2, y, resolve, reject) }, reject) } else { x.then(resolve, reject) } + } else if(x && (typeof x === 'object'|| typeof x === 'function')){ + let called = false; + try { + let then = x.then; + if(typeof then === 'function'){ + then.call(x,(y)=>{ + if(called) return; + called = true; + resolvePromise(promise2,y,resolve,reject); + },(e)=>{ + if(called) return; + called = true; + reject(e) + }) + }else{ + resolve(x) + } + } catch (error) { + if(called) return; + called = true; + reject(error) + } + } else { resolve(x) } } 複製代碼
修改完了以後,咱們來看看結果
固然返回一個有then方法的函數結果也是同樣的
能夠看見我們家的promise,又一次完成進化,如今快成長成一個獨當一面的promise了
咱們來看看對比
觀察能夠發現
咱們畫個圖
這是一個正常狀況
當2這onFulfilled返回的是上面整個then時,就陷入了自我循環
因此這裏,咱們阻止一下自我循環
class myPromise {
... } function resolvePromise(promise2, x, resolve, reject) { + if(promise2===x) { + return reject(new TypeError('自我循環')) + } if (x instanceof myPromise) { ... } } 複製代碼
這裏是約定,因此沒有啥理由
咱們來加上
then(onFulfilled, onRejected) {
+ onFulfilled = typeof onFulfilled === 'function'? onFulfilled:y=>y; + onRejected = typeof onRejected === 'function'? onRejected:y=>{throw y;} let promise2 = new myPromise((resolve, reject) => { 複製代碼
暫時不知道爲何,有知道的大佬說明一下 這個也是一個約定,咱們來看一個例子
觀察以後,能夠發現,resolve的promise傳遞是reslove的值,而reject是直接傳遞promise實例 因此咱們來改造我們家的promise
const resolve = (value) => {
+ if (value instanceof myPromise) { + return value.then(resolve, reject) + } if (this.state === "pending") { this.state = "fulfilled"; this.value = value; this.onFulfilledCallbacks.forEach((fn) => fn(value)); } }; 複製代碼
到這裏,我們家的promise,大概就是這個樣子的
class myPromise {
constructor(executor) { this.state = "pending"; //內部狀態爲pending,resolve,reject this.value = null; this.reason = null; this.onFulfilledCallbacks = []; this.onRejectedCallbacks = []; const resolve = (value) => { if (value instanceof myPromise) { return value.then(resolve, reject) } if (this.state === "pending") { this.state = "fulfilled"; this.value = value; this.onFulfilledCallbacks.forEach((fn) => fn(value)); } }; const reject = (reason) => { if (this.state === "pending") { this.state = "rejected"; this.reason = reason; this.onRejectedCallbacks.forEach((fn) => fn(reason)); } }; try { executor(resolve, reject); } catch (e) { reject(e); } } then(onFulfilled, onRejected) { onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : y => y; onRejected = typeof onRejected === 'function' ? onRejected : y => { throw y; } const promise2 = new myPromise((resolve, reject) => { if (this.state === "fulfilled") { setTimeout(() => { // 萬一onFulfilled方法報錯,咱們用trycatch捕獲一下 try { let x = onFulfilled(this.value); resolvePromise(promise2, x, resolve, reject) } catch (error) { reject(error) } }) } if (this.state === "rejected") { setTimeout(() => { try { let x = onRejected(this.reason); resolvePromise(promise2, x, resolve, reject) } catch (error) { reject(error) } }) } if (this.state === "pending") { this.onFulfilledCallbacks.push(value => { setTimeout(() => { try { let x = onFulfilled(value) resolvePromise(promise2, x, resolve, reject) } catch (error) { reject(error) } }) }); this.onRejectedCallbacks.push(reason => { setTimeout(() => { try { let x = onRejected(reason) resolvePromise(promise2, x, resolve, reject) } catch (error) { reject(error) } }) }); } }) return promise2; } } function resolvePromise(promise2, x, resolve, reject) { if (x === promise2) { return new TypeError('自我循環') } if (x instanceof myPromise) { if (x.state === 'pending') { x.then((y) => { resolvePromise(promise2, y, resolve, reject) }, reject) } else { x.then(resolve, reject) } } else if (x && (typeof x === 'object' || typeof x === 'function')) { let called = false; try { let then = x.then; if (typeof then === 'function') { then.call(x, (y) => { if (called) return; called = true; resolvePromise(promise2, y, resolve, reject); }, (e) => { if (called) return; called = true; reject(e) }) } else { resolve(x) } } catch (error) { if (called) return; called = true; reject(error) } } else { resolve(x) } } 複製代碼
最後用promises-aplus-tests測試一下咱們的promise
npm init npm i promises-aplus-tests -D 複製代碼
修改一下package.json
"scripts": {
// 後面接你的文件 "test": "promises-aplus-tests ./src/index.js" }, 複製代碼
執行
npm run test
複製代碼
最後發現有40測試沒經過
這裏,其餘的文章會告訴這是promise的規範,就彷彿回到了小學時代,我懵懵懂懂的問老師問題時,老師告訴我只須要記住就好了。 可是,我拒絕!!!
咱們來看一個極端的例子
爲何不同的呢?
究其根本緣由,resolvePromise返回了一個狀態爲fuifilled的promise
在promise內部的resolvePromise()方法內,直接執行了x.then(reslove,reject)
因此把custom thenable當成了值,錯誤的返回了
這裏怎麼處理呢
class myPromise {
constructor(executor) { this.state = "pending"; //內部狀態爲pending,resolve,reject this.value = null; this.reason = null; this.onFulfilledCallbacks = []; this.onRejectedCallbacks = []; const resolve = (value) => { if (value instanceof myPromise) { return value.then(resolve, reject); } + setTimeout(() => { if (this.state === "pending") { this.state = "fulfilled"; this.value = value; this.onFulfilledCallbacks.forEach((fn) => fn(value)); } + }) }; const reject = (reason) => { + setTimeout(()=>{ if (this.state === "pending") { this.state = "rejected"; this.reason = reason; this.onRejectedCallbacks.forEach((fn) => fn(reason)); } + }) }; try { executor(resolve, reject); } catch (e) { reject(e); } } then(onFulfilled, onRejected) { onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : y => y; onRejected = typeof onRejected === 'function' ? onRejected : y => { throw y; } const promise2 = new myPromise((resolve, reject) => { if (this.state === "fulfilled") { setTimeout(() => { // 萬一onFulfilled方法報錯,咱們用trycatch捕獲一下 try { let x = onFulfilled(this.value); resolvePromise(promise2, x, resolve, reject) } catch (error) { reject(error) } }) } if (this.state === "rejected") { setTimeout(() => { try { let x = onRejected(this.reason); resolvePromise(promise2, x, resolve, reject) } catch (error) { reject(error) } }) } if (this.state === "pending") { this.onFulfilledCallbacks.push(value => { - setTimeout(() => { try { let x = onFulfilled(value) resolvePromise(promise2, x, resolve, reject) } catch (error) { reject(error) } - }) }); this.onRejectedCallbacks.push(reason => { - setTimeout(() => { try { let x = onRejected(reason) resolvePromise(promise2, x, resolve, reject) } catch (error) { reject(error) } - }) }); } }) return promise2; } } function resolvePromise(promise2, x, resolve, reject) { if (x === promise2) { return reject(new TypeError('自我循環')) } if (x instanceof myPromise) { if (x.state === 'pending') { x.then((y) => { resolvePromise(promise2, y, resolve, reject) }, reject) } else { x.then(resolve, reject) } } else if (x && (typeof x === 'object' || typeof x === 'function')) { let called = false; try { let then = x.then; if (typeof then === 'function') { then.call(x, (y) => { if (called) return; called = true; resolvePromise(promise2, y, resolve, reject); }, (e) => { if (called) return; called = true; reject(e) }) } else { resolve(x) } } catch (error) { if (called) return; called = true; reject(error) } } else { resolve(x) } } 複製代碼
咱們把全部的resolve/reject都改爲異步觸發
咱們執行 執行
npm run test
複製代碼
終於經過了所有的測試用例了
class myPromise {
constructor(executor) { this.state = "pending"; //內部狀態爲pending,resolve,reject this.value = null; this.reason = null; this.onFulfilledCallbacks = []; this.onRejectedCallbacks = []; const resolve = (value) => { if (value instanceof myPromise) { return value.then(resolve, reject); } setTimeout(() => { if (this.state === "pending") { this.state = "fulfilled"; this.value = value; this.onFulfilledCallbacks.forEach((fn) => fn(value)); } }); }; const reject = (reason) => { setTimeout(() => { if (this.state === "pending") { this.state = "rejected"; this.reason = reason; this.onRejectedCallbacks.forEach((fn) => fn(reason)); } }); }; try { executor(resolve, reject); } catch (e) { reject(e); } } then(onFulfilled, onRejected) { onFulfilled = typeof onFulfilled === "function" ? onFulfilled : (y) => y; onRejected = typeof onRejected === "function" ? onRejected : (y) => { throw y; }; const promise2 = new myPromise((resolve, reject) => { if (this.state === "fulfilled") { setTimeout(() => { // 萬一onFulfilled方法報錯,咱們用trycatch捕獲一下 try { let x = onFulfilled(this.value); resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); } }); } if (this.state === "rejected") { setTimeout(() => { try { let x = onRejected(this.reason); resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); } }); } if (this.state === "pending") { this.onFulfilledCallbacks.push((value) => { try { let x = onFulfilled(value); resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); } }); this.onRejectedCallbacks.push((reason) => { try { let x = onRejected(reason); resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); } }); } }); return promise2; } } function resolvePromise(promise2, x, resolve, reject) { if (x === promise2) { return reject(new TypeError("自我循環")); } if (x instanceof myPromise) { if (x.state === "pending") { x.then((y) => { resolvePromise(promise2, y, resolve, reject); }, reject); } else { x.then(resolve, reject); } } else if (x && (typeof x === "object" || typeof x === "function")) { let called = false; try { let then = x.then; if (typeof then === "function") { then.call( x, (y) => { if (called) return; called = true; resolvePromise(promise2, y, resolve, reject); }, (e) => { if (called) return; called = true; reject(e); } ); } else { resolve(x); } } catch (error) { if (called) return; called = true; reject(error); } } else { resolve(x); } } myPromise.deferred = function () { let defer = {}; defer.promise = new myPromise((resolve, reject) => { defer.resolve = resolve; defer.reject = reject; }); return defer; }; module.exports = myPromise; 複製代碼
本文使用 mdnice 排版