admin管理员组文章数量:1336632
I was trying to understand the difference between resolve(thenable)
and resolve('non-thenable-object')
.
In examples below, use promise instead of thenable
because promise is also thenable
and may be easier to understand.
Demo1: resolve(promise)
let resolvePromise = new Promise(resolve => {
let resolvedPromise = Promise.resolve()
resolve(resolvedPromise)
})
resolvePromise.then(() => {
console.log('resolvePromise resolved')
})
let resolvedPromiseThen = Promise.resolve().then(res => {
console.log('promise1')
})
resolvedPromiseThen
.then(() => {
console.log('promise2')
})
.then(() => {
console.log('promise3')
})
I was trying to understand the difference between resolve(thenable)
and resolve('non-thenable-object')
.
In examples below, use promise instead of thenable
because promise is also thenable
and may be easier to understand.
Demo1: resolve(promise)
let resolvePromise = new Promise(resolve => {
let resolvedPromise = Promise.resolve()
resolve(resolvedPromise)
})
resolvePromise.then(() => {
console.log('resolvePromise resolved')
})
let resolvedPromiseThen = Promise.resolve().then(res => {
console.log('promise1')
})
resolvedPromiseThen
.then(() => {
console.log('promise2')
})
.then(() => {
console.log('promise3')
})
result:
- promise1
- promise2
- resolvePromise resolved
- promise3
Demo2: resolve('non-thenable-object')
let resolvePromise = new Promise(resolve => {
resolve('non-thenable-object')
})
resolvePromise.then(() => {
console.log('resolvePromise resolved')
})
let resolvedPromiseThen = Promise.resolve().then(res => {
console.log('promise1')
})
resolvedPromiseThen
.then(() => {
console.log('promise2')
})
.then(() => {
console.log('promise3')
})
result:
- resolvePromise resolved
- promise1
- promise2
- promise3
So, I checked the spec and found Promise Resolve Functions . Then got to PromiseResolveThenableJob and EnqueueJob.
So, according to the spec, I think demo1 was like
Demo3:
let resolvePromise = new Promise(resolve => {
let resolvedPromise = Promise.resolve()
// resolve(resolvedPromise)
// works like
Promise.resolve().then(() => {
Promise.resolve(resolvedPromise).then(() => {
resolve()
})
})
})
resolvePromise.then(() => {
console.log('resolvePromise resolved')
})
let resolvedPromiseThen = Promise.resolve().then(res => {
console.log('promise1')
})
resolvedPromiseThen
.then(() => {
console.log('promise2')
})
.then(() => {
console.log('promise3')
})
I think so because Promise Resolve Functions says:
- Perform EnqueueJob("PromiseJobs", PromiseResolveThenableJob, « promise, resolution, thenAction »).
And PromiseResolveThenableJob says:
This Job uses the supplied thenable and its then method to resolve the given promise. This process must take place as a Job to ensure that the evaluation of the then method occurs after evaluation of any surrounding code has pleted.
Also, I think demo2 works like
Demo4:
//let resolvePromise = new Promise(resolve => {
//resolve('str')
//})
//works like
let resolvePromise = Promise.resolve('str')
resolvePromise.then(() => {
console.log('resolvePromise resolved')
})
let resolvedPromiseThen = Promise.resolve().then(res => {
console.log('promise1')
})
resolvedPromiseThen
.then(() => {
console.log('promise2')
})
.then(() => {
console.log('promise3')
})
As the Promise Resolve Functions says:
If IsCallable(thenAction) is false, then Return FulfillPromise(promise, resolution).
Though the results between Demo1-Demo3 and Demo2-Demo4 are equal, I am still not sure if I was right. So, I am here to ask
whether my logic is right? If not, how do you explain the different orders
between resolve(thenable)
and resolve(non-thenable)
?
- 2 I remend in general to never rely on callback invocation order between unrelated promises. Although the spec gives a specific queuing semantic, it should never be relevant in practice. If you need a specific order because your callbacks depend on each other, be explicit about that by chaining your promises after each other. – Bergi Commented Dec 22, 2018 at 11:47
- 3 @Bergi, Actually, in practice, I always use promises chain to control the async order. But I really want to understand the spec and principle. – xianshenglu Commented Dec 22, 2018 at 12:26
- 2 Upvoted for the ment. Nothing is wrong with genuine interest in understanding the specification for the sake of understanding, even if it's not good to rely on in practice. – Patrick Roberts Commented Dec 23, 2018 at 2:13
2 Answers
Reset to default 3After reading the specification and testing many times I thought I might get it.
Before we start, we have to settle something.
let's call it RESOLVE()
when using resolve
in Promise executor
. For example, RESOLVE(thenable)
means the code like:
new Promise((resolve,reject)=>{
resolve(thenable)
})
while resolve(thenable)
means Promise.resolve(thenable)
Ok, let's begin.
Promise.resolve('non-thenable')
and RESOLVE('non-thenable')
When we are using Promise.resolve('non-thenable')
it es to Promise.resolve
Then it es to PromiseResolve
That's the where Promise.resolve('non-thenable')
was transformed to
new Promise(resolve=>{
resolve('non-thenable')
})
So, we have the conclusion:
Promise.resolve('non-thenable')
can be transformed intoRESOLVE('non-thenable')
RESOLVE(thenable)
demo1
let resolveThenable = new Promise((resolve, reject) => {
let thenable = {
then: function (resolve, reject) {
console.log('in thenable')
resolve(42)
}
}
resolve(thenable)
// works like
// Promise.resolve().then(() => {
// thenable.then(resolve)
// })
// should be ?
// Promise.resolve().then(() => {
// thenable.then.[[Value]](resolve)
// })
// equivalent to?
// Promise.resolve().then(() => {
// thenable.then(resolve)
// })
})
resolveThenable.then(() => {
console.log('resolveThenable resolved')
})
let resolvedPromiseThen = Promise.resolve().then(res => {
console.log('promise1')
})
resolvedPromiseThen
.then(() => {
console.log('promise2')
})
.then(() => {
console.log('promise3')
})
// 'in thenable'
// 'promise1'
// 'resolveThenable resolved'
// 'promise2'
// 'promise3'
According to Promise Resolve Functions, when we were using RESOLVE(thenable)
it es to
Then it es to PromiseResolveThenableJob
This would make RESOLVE(thenable)
works like
Promise.resolve().then(() => {
thenable.then.[[Value]](resolve)
})
So, I thought it is equivalent to
Promise.resolve().then(() => {
thenable.then(resolve)
})
Which got the same result as RESOLVE(thenable)
.
So, we can say
RESOLVE(thenable)
can be transformed to
Promise.resolve().then(() => {
thenable.then(resolve)
})
demo2
let resolvePromise = new Promise((resolve, reject) => {
let resolvedPromise = Promise.resolve()
resolve(resolvedPromise)
// works like
// Promise.resolve().then(() => {
// resolvedPromise.then(() => {
// resolve()
// })
// })
// should be?
// Promise.resolve().then(() => {
// resolvedPromise.then.[[Value]](resolve,reject)
// })
// equivalent to ?
// Promise.resolve().then(() => {
// resolvedPromise.then(resolve)
// })
// equivalent to ?
// Promise.resolve().then(() => {
// resolvedPromise.then(() => {
// resolve()
// })
// })
})
resolvePromise.then(() => {
console.log('resolvePromise resolved')
})
let resolvedPromiseThen = Promise.resolve().then(res => {
console.log('promise1')
})
resolvedPromiseThen
.then(() => {
console.log('promise2')
})
.then(() => {
console.log('promise3')
})
// 'promise1'
// 'promise2'
// 'resolvePromise resolved'
// 'promise3'
When we talked about RESOLVE(resolvedPromise)
, we can find the spec doesn't distinguish thenable
from promise
. So, in the same way, RESOLVE(resolvedPromise)
can be transformed into
Promise.resolve().then(() => {
resolvedPromise.then(resolve)
})
Though, in this case, the order between RESOLVE(thenable)
and RESOLVE(promise)
is different. Because thenable.then
is a sync operation while resolvedPromise.then
is an async operation. They are not the same then
method.
So, here is our conclusion:
Both
RESOLVE(thenable)
andRESOLVE(promise)
can be transformed into
new Promise((resolve, reject) => {
Promise.resolve().then(() => {
thenable.then(resolve)
})
})
Promise.resolve(thenable)
It is quite simple when using Promise.resolve(promise)
because it returns promise
argument.
However, things bee plicated when using Promise.resolve(thenable)
and the thenable
is not a promise. Let's call it Promise.resolve(nonPromiseThenable)
.
According to Promise.resolve ( x )
Then it es to
So, Promise.resolve(nonPromiseThenable)
can be transformed to
new Promise(resolve => {
resolve(nonPromiseThenable)
})
And finally es to
new Promise(resolve => {
Promise.resolve().then(() => {
nonPromiseThenable.then(resolve)
})
})
You can test it in the demo below.
var thenable = {
then(resolve, reject) {
resolve(1)
}
}
// code transformation
Promise.resolve(thenable).then(res => {
console.log(res)
})
// equal
// new Promise(resolve => {
// resolve(thenable)
// }).then(res => {
// console.log(res)
// })
// equal
// new Promise(resolve => {
// Promise.resolve().then(() => {
// thenable.then(resolve)
// })
// }).then(res => {
// console.log(res)
// })
new Promise(resolve => resolve(2))
.then(res => {
console.log(res)
})
.then(res => console.log(3))
In the end, let's make a conclusion:
Promise.resolve('nonThenable')
can be transformed intoRESOLVE('nonThenable')
. They have the same effects.Promise.resolve(thenable)
is different fromRESOLVE(thenable)
. They have different effects.RESOLVE(thenable)
andRESOLVE(promise)
can be transformed intonew Promise((resolve, reject) => { Promise.resolve().then(() => { thenable.then(resolve) }) })
Promise.resolve(promise) === promise
whilePromise.resolve(nonPromiseThenable)
can be transformed intonew Promise(resolve => { Promise.resolve().then(() => { nonPromiseThenable.then(resolve) }) })
Yes, your logic looks right.
new Promise(resolve => resolve('non-thenable-object'))
is equivalent to Promise.resolve('non-thenable-object')
for all purposes.
In your Demo3 I would however remend to leave out Promise.resolve(resolvedPromise)
. I'm not sure whether that was intentional or not, but Promise.resolve
does have a shortcut when its argument is already a promise, and then returns the resolvedPromise
as-is. You'd rather write
new Promise((resolve, reject) => {
let resolvedPromise = Promise.resolve();
// resolve(resolvedPromise) works like
Promise.resolve().then(() => resolvedPromise.then(resolve, reject));
});
本文标签:
版权声明:本文标题:javascript - What's the difference between resolve(thenable) and resolve('non-thenable-object')? - Stack 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742412658a2470099.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论