群里看到,不懂就查,查不懂就对线源码。
题目
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
逻辑
首先设1
为.then(() => { console.log(1) })
这一个微任务,
其他同理。
一开始执行完两个Promise.resolve()
以后:
microTask: `0 1`
Promise.resolve(4)
返回一个状态为fulfilled
的Promise
此时按逻辑应该把4
加入到微任务中了,
但是在then
中返回fulfilled
状态的Promise
的话,
Promise
内部会将返回的Promise
的then
方法执行放入到微任务队列中执行。
microTask: 1 Promise.resolve(4).then
microTask: Promise.resolve(4).then 2
而then
内部因为Promise.resolve(4)
状态已经是fulfilled
了,
又申请了个微任务为了让0
同步Promise.resolve(4).then
的fulfilled
的状态,
因为需要等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
证明 Then方法会放入微队列中
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
,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
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!