Reputation: 3739
I have the following code:
let a, b, p = new Promise((resolve, reject) => { a = resolve; b = reject; } );
console.log(a, b); // <-- Is this guaranteed to not print two undefineds?
At my console.log line, I need to be entirely sure that a and b is set. I was wondering if the JavaScript spec somehow guarantees my correctness?
I mean, could it be a possibility that some JS runtime implementations pushes the invocation of the callback provided to the constructor, to the back of the execution stack? I.e. executing the constructor after console.log? Or is this explicitly prohibited by the specs?
Upvotes: 0
Views: 38
Reputation: 3739
Seems like ECMAScript 2015 at least guarantees it.
From https://www.ecma-international.org/ecma-262/6.0/#sec-promise-constructor:
25.4.3.1 Promise ( executor )
When the Promise function is called with argument executor the following steps are taken:
- If NewTarget is undefined, throw a TypeError exception.
- If IsCallable(executor) is false, throw a TypeError exception.
- Let promise be OrdinaryCreateFromConstructor(NewTarget, "%PromisePrototype%", «[[PromiseState]], [[PromiseResult]], [[PromiseFulfillReactions]], [[PromiseRejectReactions]]» ).
- ReturnIfAbrupt(promise).
- Set promise's [[PromiseState]] internal slot to "pending".
- Set promise's [[PromiseFulfillReactions]] internal slot to a new empty List.
- Set promise's [[PromiseRejectReactions]] internal slot to a new empty List.
- Let resolvingFunctions be CreateResolvingFunctions(promise).
- Let completion be Call(executor, undefined, «resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]]»).
- If completion is an abrupt completion, then
- Let status be Call(resolvingFunctions.[[Reject]], undefined, «completion.[[value]]»).
- ReturnIfAbrupt(status).
- Return promise.
Steps 9 and 13 guanratees that the callback will be invoked before the Promise is returned.
Upvotes: 0
Reputation: 780808
Yes, it's guaranteed. In the specification of Promise(executor)
, step 9 is:
Let completion be Call(executor, undefined, « resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]] »).
So it simply calls the executor function normally, it's not deferred in any way. Any asynchronous activity would have to be initiated within the executor. If the executor is synchronous, the results will be available immediately.
Upvotes: 2