Reputation: 2201
It is asserted the ECMAScript promises is a Promises/A+ implementation, so they have no contradictions. However, I encountered a behaviour of ecma promises which allegedly is out of line with the Promises/A+.
When we call promise1.then(onFulfilled, onRejected)
to listen to the promise1
's output, we get as a return value another promise (promise2
). When the needed callback (onFulfilled/onRejected
) was executed and it, in turn, returned some value x
, the spec prescribes to resolve it with the defined [[Resolve(promise2, x)]]
function. Let's suppose x
happened to be a promise itself (x === promise3
), then the steps must be taken is the following:
- If
x
is a promise, adopt its state:- If
x
is pending,promise2
must remain pending untilx
is fulfilled or rejected.- If/when
x
is fulfilled, fulfillpromise2
with the same value.- If/when
x
is rejected, rejectpromise2
with the same reason.
I wonder what if x
is finally fulfilled with yet another promise (promise4
) (there are not anything in the way of it, are there?). It can be concluded from the spec excerpt that promise2
must be fulfilled with promise4
too. But it is seemingly not so in the ECMAScript world:
let promise4 = new Promise((resolve) => { resolve(4) })
let promise3 = new Promise((resolve) => {
resolve(promise4);
});
let promise1 = new Promise((resolve) => {
resolve(1);
});
let promise2 = promise1.then((val) => { return promise3 });
promise2.then(val => console.log(val)); // output: 4
In the other words, promise2
is fulfilled with the promise4
's value. This behaviour is like one that is defined in the spec for other thenable
objects. So don't ECMAScript promises carry out expected type checking and just check whether x
has then
method?
Upvotes: 1
Views: 75
Reputation: 664630
Let's suppose
x
happened to be a promise itself, then the steps must be taken is the following: […]
No, they don't need to be taken - they only may be taken if x
is a "promise". These steps are an optional ("allowed", not "required") optimisation:
Note 4:
Generally, it will only be known thatx
is a true promise if it comes from the current implementation. This clause allows the use of implementation-specific means to adopt the state of known-conformant promises.
ECMAScript does not treat its own Promise
s as "known to be conformant", ignoring these steps. They simply treat native promises like all other thenables. Given there is no way to create an ECMAScript Promise
that is fulfilled with another promise, this is equivalent to directly adopting the state.
Upvotes: 1
Reputation: 350345
It can be concluded from the spec excerpt that
promise2
must be fulfilled withpromise4
too.
No, this does not follow from the Promises/A+ specification. The rule you quote from it
- If/when
x
is fulfilled, fulfillpromise2
with the same value.
...is recursive in nature. It should be understood in more elaborate terms as follows:
If/when x
is fulfilled, fulfill promise2
with the same value that x
fulfilled with.
Now for the part "that x
fulfilled with", the same Resolution Procedure applies(!): Indeed, as x
resolves with yet another thenable (promise4
), it in turn gets locked-in with the next promise in the chain (promise4
in your example). This is not yet the fulfilled value. -- there is an important difference between resolving and fulfilling. This second execution of the Resolution Procedure will make sure that the value that x
fulfils with, is the value that promise4
fulfils with.
The chain of locked-in promises can have any length, but the principle remains the same: each will resolve by locking into the next promise through this Promises/A+ Resolution Procedure. When the last one in this chain fulfils (with a non-thenable value), then all promises that are locked-in will get fulfilled with this value.
Upvotes: 0