看過不少種 promise 的實現,一直想本身寫一個,吭哧了好久,終於寫出來了(先不寫 all 等方法和 reject 方法,後期在 issues 中補充),就拿它做爲第一篇博客吧promise
代碼瀏覽器
let proB = new PromiseB((resolve) => { console.log('promiseB: resolve'); resolve('then1') })
proB.then(value => {
console.log('then1', value)
return 'then2'
}).then(//建立pro3
data => {
return new PromiseB((resolve) => {//是pro4
setTimeout(() => {
console.log('非正常then2:', data)
resolve('then3')
}, 1000)
})
}).then(value => {
console.log('數據then3', value)
return 'then4'
}).then(value => {
console.log('數據then4', value)
return 'then5'
}).then().then(
value => { console.log('then5:', value) }
)
複製代碼
本身實現執行結果: 異步
promise 執行的結果: async
先看一下使用中須要注意的方面函數
具體實現思路ui
class PromiseB{
constructor(excutor){
this.state='pending'// 'pending'|'fulfilled'|'redected'
excutor(this.resolve)
}
then=(onFunfilled,onRejected)=>{//class properties語法,目前谷歌瀏覽器已經支持了
return new PromiseB(/*這裏應該有一個函數參數*/)
}
}
複製代碼
class PromiseB{
constructor(excutor) {
this.state='pending'// 'pending'|'fulfilled'|'redected'
this.value = null
this.asyncObj = {}
excutor(this.resolve)
}
then=(onFunfilled,onRejected)=>{//class properties語法,目前谷歌瀏覽器已經支持了
return new PromiseB(/*這裏應該有一個函數參數*/)
}
resolve = (newValue) => {}
}
複製代碼
then = (onFUlfilled) => {
return new PromiseB(resolve => {
if (this.state === "pending") {
this.asyncObj={ onFUlfilled, resolve };
} else {
if(!onFUlfilled)return resolve(this.value)
resolve(onFUlfilled(this.value));
}
});
};
複製代碼
resolve = newValue => {
this.state = "fulfilled";
this.value = newValue;
};
複製代碼
resolve = newValue => {
if (newValue && newValue.then) {
newValue.then(this.resolve);
} else {
this.state = "fulfilled";
this.value = newValue;
if(!asyncObj.onFUlfilled && asyncObj.resolve)return asyncObj.resolve(this.value)
asyncObj.resolve(asyncObj.onFUlfilled(this.value))
}
};
複製代碼
所有代碼實現:this
class PromiseB {
constructor(excutor) {
this.state = "pending";
this.value = null;
this.asyncObj = {};
excutor(this.resolve);
}
then = onFulfilled =>
new PromiseB(resolve => {
if (this.state === "pending")
return (this.asyncObj = { onFulfilled, resolve });
if (!onFulfilled) return resolve(this.value);
resolve(onFulfilled(this.value));
});
resolve=value=>{
if(value&&value.then){
value.then(this.resolve)
}else{
this.state='fulfilled'
this.value=value
setTimeout(() => {
const {onFulfilled,resolve} = this.asyncObj
if(onFulfilled&&resolve)resolve(onFulfilled(this.value))
if(!onFulfilled&&resolve)resolve(this.value)
},
0);
}
}
}
複製代碼
由於在參數不爲 promise 而且 asyncObj 有值的狀況下,看第 23 行代碼,這裏實際上是一個遞歸,onFulfiled 其實就是該 promise 的 then 的參數,resolve 是下個 prommsie 的 resolve。實現了遞歸遍歷數據。spa
其實通常來講,若是真的看懂了上面的代碼是不會有這個疑問的,這裏並不算是發佈訂閱, 通常咱們發佈訂閱都是存一系列的 callback,一次 emit,執行全部回調,咱們這裏是遞歸,每次執行的時候只有一個以前存好的 onFulfilled 和一個 resolve調試
這個其實得留到斷點分析裏去講,由於篇幅有點長,並且我本身感受也沒有徹底搞清楚,我是逆推分析出來的。code
其實爲了搞懂上面那些東西,我用了差很少三天的時間,最後經過編號和打斷點才搞清楚地。其實就幾個問題,若是都能搞清楚,那你應該對 promise 沒有任何疑問了。
答案在文中,結果在底部
最好先想一下上面的問題,若是答案不對或者沒有搞很清楚,帶着疑問往下看,收穫會更大。生成的第幾個promise就記作pro幾,例如第一個promise就叫pro1。pro1的onfulfilled就是pro1的then的參數onfulfilled.
excutor(resolve)
,即執行 console.log('promiseB: resolve’)
,並觸發 pro1.resolve('then1')
,步驟1結束pro1.resolve('then1')
觸發, 判斷傳入的值是否爲promise,值'then1'不是promise:pro1.value改變爲pro1.resolve參數'then1',pro1狀態改變,執行setTimeout裏的代碼,由於asyncObj爲空,其實啥都不會執行,步驟2結束。proB.then...
執行,拉開了promise chain的序幕。 pro1.then(onFulfilled)
觸發,返回新的promise pro2 ,判斷pro1的狀態,經過:執行Pro1的onFulfilled-> value=>{console.log('then1', value)return 'then2'}
,執行完畢之後獲取到返回值'then2',將'then2'做爲pro2.resolve的參數,即執行 pro2.resolve('then2')
,步驟3結束pro2.resolve('then2')
觸發,判斷傳入的值是否爲promise,值'then2'不是promise:pro2.value改變爲pro2.resolve參數‘then2’,pro2狀態改變,執行setTimeout裏的代碼,由於asyncObj爲空,其實啥都不會執行,步驟4結束。pro2.then(onFulfilled)
觸發,返回新的promise pro3 ,判斷pro2的狀態,經過,執行pro2的then的onfulfilled->data => { return new PromiseB((resolve) => {setTimeout(() => { console.log('非正常then2:', data) resolve('then3') }, 1000) })}
,建立並執行pro4的excutor(resolve),setTimeout(() => { console.log('非正常then2:', data) resolve('then3') }, 1000) })
,這個resolve是pro4的,獲得返回值 一個promise即pro4 ,將返回值做爲value傳遞給pro3的resolve,執行pro3.resolve(pro4)
,步驟5結束pro3.resolve(pro4)
觸發,判斷傳入的值是否爲promise,值 pro4 是promise:執行 pro4.then(pro3.resolve)
,步驟6結束。pro4.then(pro3.resolve)
觸發,返回新的promise pro5,判斷pro4的狀態,由於狀態的改變都是在this.resolve執行且參數不是promise的狀況下才會改變,而pro4.resolve尚未執行,因此 不經過 :將 參數promise即pro4 的 onfulfilled即pro3的resolve 和 pro5的resolve 存起來,存到 參數promise即pro4的asyncObj 中,即此時 pro4.asyncObj={onfulfilled:pro3.resolve,resolve:pro5.resolve}
。步驟7結束,執行完畢之後繼續回到promise chain,此時應該執行的是 pro3.then(onFulfilled)
pro3.then(onFulfilled)
觸發(我以前的思路一直是卡在步驟7結束)。返回新的promise pro6 ,判斷pro3的狀態,由步驟6可知,不經過:將pro3的onFulfilled-> (value => {console.log('數據then3', value)return 'then4'})
和pro6的resolve存到pro3的asyncObj中,即此時pro3.asyncObj={onfulfilled:pro3.onFulfilled,resolve:pro6.resolve}
,返回pro6,執行 pro6.then(onFulfilled)
步驟8結束。pro6.then(onFulfilled)
觸發,返回新的promise pro7 ,判斷pro6的狀態,和步驟7中pro4對於狀態的判斷一致,不經過:將pro6的onfulfilled->value=>{console.log('數據then4', value)return 'then5'}
和pro7的resolve存到pro6的asyncObj中,即此時 pro6.asyncObj={onfulfilled:pro6.onFulfilled,resolve:pro7.resolve}
,返回pro7,執行pro7.then(onFulfilled)
,步驟9結束pro7.then(onFulfilled)
觸發,返回新的promise pro8 ,判斷pro7的狀態,和步驟7中pro4對於狀態的判斷一致,不經過:將pro7的onfulfilled->undefined
和pro8的resolve存到pro7的asyncObj中,即此時 pro7.asyncObj={onfulfilled:pro7.onFulfilled,resolve:pro8.resolve}
,返回pro8,執行pro8.then(onFulfilled)
,步驟10結束pro8.then(onFulfilled)
觸發,返回新的promise pro9 ,判斷pro8的狀態,和步驟7中pro4對於狀態的判斷一致,不經過:將pro8的onfulfilled->value => {console.log('then5:', value) }
和pro9的resolve存到pro8的asyncObj中,即此時 pro8.asyncObj={onfulfilled:pro8.onFulfilled,resolve:pro9.resolve}
,返回pro9,由於pro9沒有then,因此 沒有建立新的pro10 ,promise chain的then或者說同步過程結束,執行promise chain 之後的邏輯,直到參數promise,即pro4的resolve被觸發,才繼續執行promise chain,步驟11結束。pro4.resolve('then3')
觸發,判斷傳入的值是否爲promise,值'then3'不是promise:pro4.value改變爲pro4.resolve參數'then3',pro4狀態改變,執行setTimeout裏的代碼,由步驟7可知 pro4.asyncObj={onfulfilled:pro3.resolve,resolve:pro5.resolve}
。先執行 let nnvalue = onfulfilled('then3')
,獲得結果之後執行 pro5.resolve(nnvalue)
,onfulfilled('then3')觸發,onfulfiled爲pro3.resolve,即執行 pro3.resolve('then3')
,可是步驟13其實尚未結束,由於pro5.resolve(nnvalue)
尚未執行。pro3.resolve('then3')
觸發,判斷傳入的值是否爲promise,值'then3'不是promise:pro3.value改變爲pro3.resolve參數'then3',pro3狀態改變 ,執行setTimeout裏的代碼,由步驟8可知pro3.asyncObj={onfulfilled:pro3.onFulfilled,resolve:pro6.resolve}
,可是其實這裏還有一步,此時進入setTimeout就是異步執行了,而在步驟13中還有一步沒有執行,哪裏屬於主邏輯,先去執行pro5.resolve(nnvalue)
,由於let nnvalue = onfulfilled('then3')===pro3.resolve('then3')
,pro3.resolve('then3')沒有返回值,因此nnvalue=undefined, pro5.resolve(undefined)
執行,判斷參數undefined不是promise,修改pro5.value爲undefined,修改狀態,調出pro5.asyncObj,執行內部函數,由步驟7可知 pro5.then
未被調用過,因此其asyncObj爲空,至此步驟13結束,可是步驟14仍在繼續 ,等主流程即步驟13結束之後,步驟14setTimeout內的函數開始執行-> let nnvalue=pro3.onFulfilled('then3')-> let nnValue= (value => {console.log('數據then3', value)return 'then4'})('then3')
,獲得nnvalue='then4',而後執行pro3.asyncObj.resolve(nnvalue)
即 pro6.resolve('then4')
,其實從13結束之後就開始了遞歸啦,步驟14結束。pro6.resolve('then4')
觸發,判斷參數'then4'是否爲promise,不是:修改 pro4.value='then4'
,修改狀態,執行定時器,等待主進程結束,執行定時器內部代碼,由步驟9可得 pro6.asyncObj={onfulfilled:pro6.onFulfilled,resolve:pro7.resolve}
,pro6.onfulfilled('then4')->(value=>{console.log('數據then4', value)return 'then5'})('then4')
,而後獲得結果nnvalue爲 'then5', 執行 pro6.asyncObj.resolve('then5')
即 pro7.resolve('then5')
,步驟15結束pro7.resolve('then5')
觸發,判斷參數'then5'是否是promise,不是:修改pro7.value='then5'
,修改狀態,執行定時器,等待主進程結束,執行定時器內部代碼,由步驟10可得 pro7.asyncObj={onfulfilled:pro7.onFulfilled,resolve:pro8.resolve}
,由於pro7.onFulfilled=undefined,執行pro7.asyncObj.resolve('then5')
即pro8.resolve('then5')
,步驟16結束pro8.resolve('then5')
觸發,判斷參數'then5'是否是promise,不是:修改pro8.value='then5'
,修改狀態,執行定時器,等待主進程結束,執行定時器內部代碼,由步驟11可得 pro8.asyncObj={onfulfilled:pro8.onFulfilled,resolve:pro9.resolve}
,執行pro8的onfulfilled->(value => {console.log('then5:', value) })('then5')
,獲得 nnvalue=undefined
執行pro8.asyncObj.resolve(undefined)
即pro9.resolve(undefined)
,步驟17結束pro9.resolve(undefined)
觸發,判斷參數undefined是否爲promise,不是:修改pro9.value=undefined
,修改狀態,執行定時器,由於pro9.then沒有執行過,因此pro9.asyncObj沒有值,因此結束。整個promise鏈也結束。