羣裏看到,不懂就查,查不懂就對線源碼。javascript
Promise.resolve().then(() => {
console.log(0)
return Promise.resolve(4)
}).then(res => {
console.log('res: ', res)
})
Promise.resolve().then(() => {
console.log(1);
}).then(() => {
console.log(2);
}).then(() => {
console.log(3);
}).then(() => {
console.log(5);
}).then(() =>{
console.log(6);
})
複製代碼
1 2 3 4 5 6
java
首先設1
爲.then(() => { console.log(1) })
這一個微任務,promise
其餘同理。markdown
一開始執行完兩個Promise.resolve()
之後:異步
microTask: `0 1`
複製代碼
Promise.resolve(4)
返回一個狀態爲fulfilled
的Promise
此時按邏輯應該把4
加入到微任務中了,oop
可是在then
中返回fulfilled
狀態的Promise
的話,ui
Promise
內部會將返回的Promise
的then
方法執行放入到微任務隊列中執行。this
microTask: 1 Promise.resolve(4).then
microTask: Promise.resolve(4).then 2
複製代碼
而then
內部由於Promise.resolve(4)
狀態已是fulfilled
了,google
又申請了個微任務爲了讓0
同步Promise.resolve(4).then
的fulfilled
的狀態,spa
由於須要等Promise.resolve(4).then
內部暴露的Promise
初始化完畢後再執行,
因此須要一個微任務等待。
(實際爲:Promise.resolve(4).then
返回的Promise
須要一個微任務進行同步Promise.resolve(4)
返回的Promise
的fulfilled
狀態,在同步時順便也把外部0
返回的Promise
一併同步了)
注:0
返回的Promise
是同步Promise.resolve(4).then
的狀態
microTask: 2 同步狀態
microTask: 同步狀態 3
microTask: 3 4
最後輸出: 1 2 3 4 5 6
複製代碼
0
修改成
.then(() => {
console.log(0)
// return Promise.resolve(4)
return {
then(resolve) {
console.log('then')
resolve(4)
},
}
})
複製代碼
輸出:
0
1
then
2
res: 4
3
5
6
複製代碼
能夠看到then
方法是放入了微任務隊列中的。
這個then
方法中resolve
執行直接同步fulfilled
狀態到0
返回的Promise
狀態上,所以執行完then
方法下一個微任務就是輸出res
了。
我翻找了v8
在4.3.65
版本還未使用v8 Torque(tq v8內部語言)或C
實現的promise.js
的源碼,在5版本之後就使用C實現了,最新版本使用tq
實現。
經過看源碼可知Promise.resovle(x)
至關於new Promise(rs => rs(x))
,二者行爲一致,有興趣能夠試試。
首先介紹一下deferred
,deferred
指內部爲了鏈式調用建立的對象,在then
方法被調用時返回的就是deferred
,Promise
的deferred
對象也是個Promise
(廢話,不這樣咋鏈式
據上面源碼可知Promise.then
/返回Thenable
都會建立這個對象。據我感受最新返回Thenable
並不會建立這個對象,直接使用外部的deferred
對象
function PromiseDeferred() {
if (this === $Promise) {
// Optimized case, avoid extra closure.
var promise = PromiseInit(new $Promise(promiseRaw));
return {
promise: promise,
resolve: function(x) { PromiseResolve(promise, x) },
reject: function(r) { PromiseReject(promise, r) }
};
} else {
var result = {};
result.promise = new this(function(resolve, reject) {
result.resolve = resolve;
result.reject = reject;
})
return result;
}
}
複製代碼
=>
爲返回,->
爲步驟,deferred Object
簡稱爲deferred
注:以後的"同步狀態"微任務只針對非pending
狀態
then(onResolve) => deferred
-> onResolve => Promise(fulfilled)
-> Promise(fulfilled).then(deferred.resolve, deferred.reject)
-> 放入一個微任務"同步狀態"到外部 deferred 上
-> 以便鏈式調用
then(onResolve) => deferred
-> onResolve => Thenable
-> deferred.resolve(Thenable)
-> then(onResolve).then(onResolve2, onReject2)
-> deferred.promise.then(onResolve2, onReject2)
-> 不調用這個 .then 據我理解是不會將 Thenable 對象轉換成 defeerred 的
-> deferred.promise PromiseState is fulfilled
-> 執行 then 方法,onResolve2 在內部會被包裝所以
-> 執行中 Thenable 轉換成 thenDeferred 時同步執行 then 方法
-> 根據 then 方法執行後決定 thenDeferred.promise 狀態
-> thenDeferred.promise.then(onResolve, onReject)
-> 掛載 deferred.promise.then 的參數到 thenDeferr.promise.then 上
複製代碼
返回Thenable
對象:
Promise.resolve()
.then(() => {
console.log(0)
return {
then(resolve) { // 在4.x源碼中這兒是同步執行
console.log('then')
resolve(4)
},
}
})
.then(res => {
console.log('res: ', res)
})
至關於
Promise.resolve()
.then(() => {
console.log(0)
})
.then(() => { // 在4.x源碼中這兒是同步執行
console.log('then')
return 4
})
.then(res => {
console.log('res: ', res)
})
複製代碼
這是在4.3.65
版本的實現邏輯(個人理解,有誤您對
返回Promise
都是須要一個微任務,可是Thenable
又不須要,可是這是4.多的代碼實現,以後代碼改動很大,不過思路大致一致。(應該吧,我看不懂後面的了太菜了
由於這是4.3.65
的代碼了,因此不符合以前推理的邏輯也正常,雖然這個版本的代碼已經挺優雅了,可是可能爲了更優雅的實現,Thenable
/Promise
的then
要一視同仁,也得放進微任務中執行,不必作特殊處理,因此兩個的then
方法都進入了微任務隊列中處理。(我尋思挺合理的
其次個人源碼理解的返回Thenable
對象的promise
後面得再跟一個then
方法纔會執行Thenable.then
,因此須要改動並統一行爲。(多是我理解錯誤?
那麼爲何在目前的版本就是返回Promise
是要兩個微任務,而Thenable
仍是一個
據我推測在以後版本中,只要有Then
都會放入微任務隊列執行一下,若是是Promise
:
同步狀態其實至關於往一個promise
的then
方法傳入(deferred.resolve, deferred.reject)
簡稱這個行爲爲同步d
。
不討論rejected
狀態(或者說和 fulfilled
狀態差很少
PromiseState is fulfilled/Thenable Object:
設 Promise.resolve().then() 返回的 deferred 爲 d
Promise.resolve().then(() => Promise.resolve(4))
-> Promise.resolve(4) => Promise(fulfilled) 且非 deferred
-> 內部處理
-> 有 then 方法進行劫持放進微任務隊列中執行
-> 因爲 then 方法未傳入參數, 默認爲 onResolve = x => x
-> 即 Promise(fulfilled).then(x => x)
-> pending 狀態須要同步
-> Promise(fulfilled).then(x => x).then(同步d)
-> 以上是按照 4.x 邏輯來的,不過 then 方法變成異步罷了
Promise.resolve().then(() => ({ then(rs) { rs(4) }})
-> Thenable 在微任務被調用 then 方法時內部會傳入 d.resolve, d.reject 來直接同步外部,
-> 所以只須要一個微任務執行 then 方法便可
新的內部實現應該比這優雅,可是惋惜我看不懂
Promise.resolve(4).then(res => res) -> PromiseState is pending:
將當前的promise.then中放入同步狀態微任務,
以即可以同步狀態到deferred對象上
好比:
Promise.resolve().then(() => Promise.resolve(4).then(res => res))
Promise.resolve().then() 返回的是 deferred(d)
Promise.resolve(4).then(res => res) 返回的也是 deferred(thenD)
由於須要同步狀態,所以內部處理掛載上去
Promise.resolve(4).then(res => res).then(同步d)
以便d能及時更新狀態
複製代碼
前面代碼改爲
Promise.resolve()
.then(() => {
console.log(0)
return Promise.resolve(4).then(res => res) // pending 狀態掛載同步狀態微任務
}).then(res => {
console.log('res: ', res)
})
複製代碼
輸出:0 1 2 3 4 5 6
一時興起,大膽猜想,人菜想寫,若有錯誤,輕罵。
內部實現寫的好致使的結果,我反正信了。(doge