Is the Promise constructor callback executed asynchronously? - javascript

Suppose I have this code
function y(resolve, reject)
{
console.log("Result");
resolve();
}
var promise = new Promise(y);
What I want to know is whether the function y will be executed asynchronously or not.

It depends on the implementation of the promise. If we check the spec. You can find the final spec here - since this answer was originally written, it has been finalized.
Here is the relevant excerpt (you can find the original source here)
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).
The ES6 standard indicates that the fulfillment of a promise is always asynchronous (See section 25.4.5.3, Promise.prototype.then and accompanying section 25.4.5.3.1, PerformPromiseThen). I have placed the relevant material below.
PerformPromiseThen
Else if the value of promise's [[PromiseState]] internal slot is "fulfilled",
Let value be the value of promise's [[PromiseResult]] internal slot.
Perform EnqueueJob("PromiseJobs", PromiseReactionJob, «fulfillReaction, value»).
Else if the value of promise's [[PromiseState]] internal slot is "rejected",
Let reason be the value of promise's [[PromiseResult]] internal slot.
Perform EnqueueJob("PromiseJobs", PromiseReactionJob, «rejectReaction, reason»).
TLDR: the function passed to the promise is executed synchronously, but subsequent then calls are always executed asynchronously.

The other answer proves this, but let me talk about the reasoning:
Promise constructor
The promise constructor callback (as specified either in the ES6 spec or the constructor spec libraries implement) will always be executed synchronously - this is in order to extract a deferred (older form of promise construction) out of it in case you need to have access to the resolve callback:
var r;
var p new Promise(function(resolve, reject){
r = resolve;
});
// use r here, for example
arr.push(r);
then callbacks
then will always be executed asynchronously, virtually all mainstream promise implementations (Native, bluebird, $q, Q, when, rsvp, promise, jQuery (as of 3.0) etc) as well as native promises implement (or implement a superset of, with more constraints) Promises/A+.
This is exactly the reason that Promises/A+ was created out of Promises/A. Asynchronous guarantees will be preserved and Zalgo won't be released. (Also see this post).
The fact this happens (asynchronous guarantee) is completely intentional and actively prevents race conditions. Code in- and outside of then will always execute in the same order.
Here is the relevant quote:
onFulfilled or onRejected must not be called until the execution context stack contains only platform code. [3.1].

Related

What happens to callBack passed to .then()? [duplicate]

I observe deferring of completeness notifications in Firefox's promises. Following assertion fails, because onFullfilled() is called too late*.
var resolved = false;
function onFullfilled() {
resolved = true;
log("Completed");
}
Promise.resolve(true).then(onFullfilled);
assert(resolved, "Promise completed promise should call resolution hook immediately.");
When exactly onFullfilled() is guaranteed to be called on Promise resolution?
* In my case "Completed" log message appears after test framework report assertion failure.
Promise resolution hooks are always called after all sync code is executed. This is by design - and is done in order to prevent race conditions.
Since promises sometimes resolve asynchronously the specification mandates they are always resolved asynchronously so the same code path executes. Promises guard you against Zalgo.
It is specified here:
onFulfilled or onRejected must not be called until the execution context stack contains only platform code.
A lot of test frameworks - namely Mocha support testing promises directly with promise-syntax - by returning a promise.
it("does something", function(){
return aPromise; // if aPromise resolves the test passes
})
You should always give a function to "then". So you should use "onFullfilled()" instead of "onFullfilled" as parameter of "then".
So it should be like:
Promise.resolve(true).then(onFullfilled());

Race condition issues with async functions Javascript [duplicate]

I would like to get a deeper understanding of how Promises work internally.
Therefore I have some sample code:
var p1 = new Promise(
function(resolve, reject) {
window.setTimeout(
function() {
resolve('res called')
}, 2000);
});
var p2 = new Promise(
function(resolve, reject) {
window.setTimeout(
function() {
resolve('res called')
}, 2000);
});
function chainPromises() {
return p1.then(function(val) {
console.log("p1");
return p2.then(function(val) {
console.log("p2");
return val;
});
});
}
chainPromises().then(function(val) {
console.log(val);
});
Here a link to execute this code.
As you would predict, first p1 is resolved, afterwards p2 and in the end the final then prints the resolv value.
But the API ref states the following:
"then" returns a new promise equivalent to the value you return from
onFulfilled/onRejected after being passed through Promise.resolve
So it would be interesting to know WHEN exactly the "then" function is executed?
Because the final "then" in the code is chained to the chainPromises(), I first thought that
it would execute after the function chainPromises() returns something (in this case another promise).
If this would have been the case the "val" of the final "then" function would be the returned promise.
But instead, the final "then" waits until all promises inside the first "then" which are returned have been resolved.
This absolutely makes sense because in this way, the "then" functions can be stacked, but
I do not really get how this is done, since the API spec. does not really cover what "then" returns and when the "then" functions is executed.
Or in other words, why does the final "then" function wait until all the Promises are resolved inside the chainPromises() function instead of just waiting for the first returned object as the API doc says.
I hope I could make clear what I mean.. :)
About Promise resolution
The thing you're witnessing here is called recursive thenable resolution. The promise resolution process in the Promises/A+ specification contains the following clause:
onFulfilled or onRejected returns a value x, run the Promise Resolution Procedure [[Resolve]](promise2, x)
The ES6 promise specification (promises unwrapping) contains a similar clause.
This mandates that when a resolve operation occurs: either in the promise constructor, by calling Promise.resolve or in your case in a then chain a promise implementation must recursively unwrap the returned value if it is a promise.
In practice
This means that if onFulfilled (the then) returns a value, try to "resolve" the promise value yourself thus recursively waiting for the entire chain.
This means the following:
promiseReturning().then(function(){
alert(1);
return foo(); // foo returns a promise
}).then(function(){
alert(2); // will only run after the ENTIRE chain of `foo` resolved
// if foo OR ANY PART OF THE CHAIN rejects and it is not handled this
// will not run
});
So for example:
promiseReturning().then(function(){
alert(1);
return Promise.resolve().then(function(){ throw Error(); });
}).then(function(){
alert("This will never run");
});
And that:
promiseReturning().then(function(){
alert(1);
return Promise.resolve().then(function(){ return delay(2000); });
}).then(function(){
alert("This will only run after 2000 ms");
});
Is it a good idea?
It's been the topic of much debate in the promises specification process a second chain method that does not exhibit this behavior was discussed but decided against (still available in Chrome, but will be removed soon). You can read about the whole debate in this esdiscuss thread. This behavior is for pragmatic reasons so you wouldn't have to manually do it.
In other languages
It's worth mentioning that other languages do not do this, neither futures in Scala or tasks in C# have this property. For example in C# you'd have to call Task.Unwrap on a task in order to wait for its chain to resolve.
Let's start with an easy perspective: "chainPromises" returns a promise, so you could look at it this way:
// Do all internal promises
var cp = chainPromises();
// After everything is finished you execute the final "then".
cp.then(function(val) {
console.log(val);
});
Generally speaking, when returning a promise from within a "then" clause, the "then" function of the encapsulating promise will be marked as finished only after the internal "then" has finished.
So, if "a" is a promise, and "b" is a promise:
// "a"'s "then" function will only be marked as finished after "b"'s "then" function has finished.
var c = a.then(function () {
return b.then(function () {
console.log("B!");
};
};
// c is a promise, since "then" always returns a promise.
c.then(function() {
console.log("Done!");
};
So the output will be:
B!
Done!
Notice btw, that if you don't "return" the internal promise, this will not be the case:
// "a"'s "then" function will only be marked as finished without waiting for "b"'s "then" to finish.
var c = a.then(function () {
// Notice we're just calling b.then, and don't "return" it.
b.then(function () {
console.log("B!");
};
};
// c is a promise, since "then" always returns a promise.
c.then(function() {
console.log("Done!");
};
Here we can't know what would be outputted first. It could be either "B!" or "Done!".
Please check the below example regarding how promises works:
The Promise object represents the eventual completion (or failure) of an asynchronous operation, and its resulting value.
console.log('person1: shoe ticket');
console.log('person2: shoe ticket');
const promiseGirlFriendBringingTickets = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('ticket');
}, 3000);
});
promiseGirlFriendBringingTickets.then((t) => {
console.log(`person3: show ${t}`);
})
console.log('person4: shoe ticket');
console.log('person5: shoe ticket');
Promise then return promise object, not promise's resolved value. I forked your JsFiddle, and added some of mine try this.
promise.then is executed right after that promise object is resolved.
I do not know how this is done in actual promises libraries, but I was able to re-create this functionality in the following way:
1) each promise has a waitingPromises property;
2) then method returns a new promise, and the original promise's waitingPromises property points to the new promise.
In this way, the chain of .then()s creates a structure that is similar to a linked list or rather a tree (each promise can have several waiting promises). A promise can be resolved only after its 'parent' promise has been resolved. The .then method itself is executed immediately, but the corresponding promise that it creates is resolved only later.
I am not sure this is a good explanation and would love to learn about other possible approaches.
Normally code is synchronous - one statement executes like (fileopen) and there is a guarantee that the next statement will execute immediately afterwards like filewrite()
but in asynchronous operations like nodejs, you should assume that
you have no idea when the operation will complete.
You can't even assume that just because you send out one request first, and another request second, that they will return in that order
Callbacks are the standard way of handling asynchrnous code in JavaScript
but promises are the best way to handle asynchronous code.
This is because callbacks make error handling difficult, and lead to ugly nested code.
which user and programmer not readble easily so promises is the way
You can think of Promise as a wrapper on some background task. It takes in a function which needs to be executed in the background.
The most appropriate place to use a promise is where some code is dependent on some background processing and it needs to know the status of the background task which was executed. For that, the background task itself accepts two callback resolve and reject in order to convey its status to the code which is dependent on it. In layman terms, this code is the one behind it in the promise chain.
When a background task invokes resolve callback with some parameter. it's marking the background operation successful and passing the result of the background operation to the next then block which will be executed next. and if it calls reject, marking it as unsuccessful then the first catch block will be executed.
In your custom promise, you can pass an error obj to the reject callback so that next catch block is aware of the error happened in the background task.

Where is code executed asynchronously in a Promise?

The following javascript function is from You Don't Know JS: Async & Performance. According to my understanding, the first comment // start doing something that could take a while is misleading. The section of the code where something is actually done possibly asynchronously is in the function passed into the Promise constructor.
function foo(x) {
// start doing something that could take a while *misleading comment*
// construct and return a promise
return new Promise( /* executor */ function(resolve,reject){
// eventually, call `resolve(..)` or `reject(..)`,
// which are the resolution callbacks for
// the promise.
} );
}
I would fix it in the following way:
function foo(x) {
// construct and return a promise
return new Promise( /* executor */ function(resolve,reject){
// start doing something that could take a while
// then foo returns the newly created Promise
// eventually, call `resolve(..)` or `reject(..)`,
// which are the resolution callbacks for
// the promise.
} );
}
Yes, this should be fixed (thanks for filing this issue).
This reminds me a bit of the difference between the deferred pattern and the revealing constructor pattern. Starting the asynchronous task inside the promise constructor callback has two advantages:
If it throws synchronously (e.g. a syntax error, a typo in the method invocation etc), the exception will be caught implicitly and reject the promise
The resolve and reject callbacks are already in scope to be passed to the asynchronous process as callbacks.
The answer is: nowhere is code executed asynchronously in a promise. *
While the second form you show is slightly more advantageous, this is solely because it handles errors more consistently (expecting callers to handle both exceptions and rejections is poor form).
Addressing your main confusion: The promise executor function runs synchronously. From MDN:
The executor function is executed immediately by the Promise implementation, passing resolve and reject functions (the executor is called before the Promise constructor even returns the created object).
And the spec:
Returning from the executor function does not mean that the deferred action has been completed but only that the request to eventually perform the deferred action has been accepted.
It is up to you to launch any asynchronous operation that eventually calls resolve or reject:
new Promise(resolve => setTimeout(resolve, 2000))
.then(() => console.log("Async"));
console.log("Sync");
Most importantly, the Promise constructor only exists to wrap legacy functions that don't support promises already. Don't use it for anything else.
*) Actually, .then guarantees that functions passed to it never run immediately, so my first statement isn't entirely correct. The soonest they can run is at the end of the same run of the event loop, in a micro-task queue. Hardly what you're after.

Why does JavaScript Promise then handler run after other code?

I'm just trying to improve my understanding on how JavaScript Promises work. I've created the following situation:
LOG 'FOO'
RUN CALLBACK LOGGING 'CALLBACK'
LOG 'BAR'
Expect all functions to complete immediately (by this I mean they will not take an excessive/unknown amount of time to complete that you would use an async operation to complete) so that the above order of operations will happen in that order.
You can write this in the following way:
function foo(cb) {
// LOG 'FOO'
console.log('foo');
// RUN CALLBACK
cb();
}
function callback() {
// LOG 'CALLBACK'
console.log('callback');
}
foo(callback);
console.log('bar');
This produces the expected output according to the situation I specified at the beginning.
> foo
> callback
> bar
You could also write it in the following way:
function foo() {
return new Promise((resolve) => {
// LOG 'FOO'
console.log('foo');
return resolve(null);
});
}
function callback() {
// LOG 'CALLBACK'
console.log('callback');
}
foo().then(callback);
// LOG 'BAR'
console.log('bar');
This situation produces the following result:
> foo
> bar
> callback
This is where I am unclear as I am expecting foo to have completed immediately so that callback will run and log 'callback' before bar logs 'bar'
The relevant specs are here:
Promises/A+ point 2.2.4:
onFulfilled or onRejected must not be called until the execution context stack contains only platform code. [3.1].
And note 3.1 (emphasis mine):
Here “platform code” means engine, environment, and promise implementation code. In practice, this requirement ensures that onFulfilled and onRejected execute asynchronously, after the event loop turn in which then is called, and with a fresh stack. This can be implemented with either a “macro-task” mechanism such as setTimeout or setImmediate, or with a “micro-task” mechanism such as MutationObserver or process.nextTick. Since the promise implementation is considered platform code, it may itself contain a task-scheduling queue or “trampoline” in which the handlers are called.
ECMAScript 6.0 (based on Promises/A+) is a little harder to excerpt cleanly, but then resolves as in section 25.4.5.3.1:
Else if the value of promise's [[PromiseState]] internal slot is "fulfilled",
a. Let value be the value of promise's [[PromiseResult]] internal slot.
b. Perform EnqueueJob("PromiseJobs", PromiseReactionJob, «‍fulfillReaction, value»).
Else if the value of promise's [[PromiseState]] internal slot is "rejected",
a. Let reason be the value of promise's [[PromiseResult]] internal slot.
b. Perform EnqueueJob("PromiseJobs", PromiseReactionJob, «‍rejectReaction, reason»).
And the important EnqueueJob operation is defined in section 8.4 ("Jobs and Job Queues"), featuring this in its preface (bold is mine):
Execution of a Job can be initiated only when there is no running execution context and the execution context stack is empty. [...] Once execution of a Job is initiated, the Job always executes to completion. No other Job may be initiated until the currently running Job completes.
In practice, this lets you make a few simple and consistent statements:
You can count on then or catch (etc) to always behave asynchronously, never synchronously.
You'll never see multiple then or catch handlers on the same stack, even if one Promise is explicitly resolved within another Promise. This also means that recursive Promise execution doesn't risk stack overflows as a normal function call might, though you can still run out of heap space if you're careless with recursive closures in a pathological case.
Time-consuming operations queued in a then or catch handler will never block the current thread, even if the Promise is already settled, so you can queue up a number of asynchronous operations without worrying about the order or promise state.
There will never be an enclosing try block outside of a then or catch, even when calling then on an already-settled Promise, so there's no ambiguity about whether the platform should handle a thrown exception.
This is not possible due to the way promises works.
Even promises which immediate resolves runs for the next tick, what you want is sync functions not promises.
See this for example:
setTimeout(function() {
console.log("test");
}, 0);
console.log("test2");
It is impossible to print test before test2 without removing the setTimeout function, because even if the wait parameter is 0, it will run for the next tick which means that it will run when all sync code has run.
I really don't mean to be blunt, but it is because that is the way the spec says that they work. If you have a need for a piece of code to run at a certain point after a code within a promise finishes, then you should utilize the promise chain. Once you introduce asynchronous code into the mix, it is a bad idea to try and mix it with dependent, synchronous, code.
Daisy chain promises whenever you need things to depend on asynchronous code:
function foo() {
console.log('foo');
return Promise.resolve();
}
function callback() {
console.log('callback');
}
function consoler() {
console.log('bar');
}
foo().then(callback).then(consoler);
Produces:
foo
callback
bar

What does "Promise fires on the same turn of the event loop" mean?

New to NodeJS. Going through the promise tutorial ('promise-it-wont-hurt') I have the following script:
var Q = require('q');
var deferred = Q.defer();
deffered.resolve('SECOND');
deffered.promise.then(console.log);
console.log('FIRST');
The output:
FIRST
SECOND
I don't get it, I would have thought that since resolved is fired first I should see second first.
They explain that this happens because of 'Promise fires on the same turn of the event loop'. I don't understand what that means...
Basically, the point is that the promise's then handler will not run before the current flow of code has finished executing and control is returned to the execution environment (in this case Node).
This is an important characteristic of Promises/A+ compliant promises because it ensures predictability. Regardless of whether the promise resolves immediately:
function getAPromise() {
var Q = require('q');
var deferred = Q.defer();
deferred.resolve('SECOND');
return deferred.promise;
}
getAPromise().then(console.log);
console.log('FIRST');
or whether it resolves after 10 seconds:
function getAPromise() {
var Q = require('q');
var deferred = Q.defer();
setTimeout(function () {
deferred.resolve('SECOND');
}, 10000);
return deferred.promise;
}
getAPromise().then(console.log);
console.log('FIRST');
you can be assured that FIRST will always be logged first.
This is discussed at length in chapters 2 and 3 of You don't know JS - async & performance. Asynchronous operations that sometimes run asynchronously and sometimes run synchronously are called Zalgos, and they are not considered to be a good thing.
It's important to note that the widely used promises in jQuery do not obey this behavior and have a number of other problems as well. If you find yourself with a jQuery promise, wrap it in a proper promise and proceed:
Q($.ajax(...)).then(breatheWithEase);
They explain that this happens because of 'Promise fires on the same turn of the event loop'. I don't understand what that means...
Me neither, imho this part doesn't make much sense. It probably should mean that when you call resolve or reject, the promise is settled immediately, and from then on will not change its state. This has nothing to do with the callbacks yet.
What is more important to understand is the next sentence in that paragraph:
You can expect that the functions passed to the "then" method of a promise will be called on the NEXT turn of the event loop.
It's like a simple rule of thumb: then callbacks are always called asynchronously. Always, in every proper promise implementation; this is mandated by the Promises/A+ specification.
Why is this? For consistency. Unlike in your example snippet, you don't know how or when a promise is resolved - you just get handed it back from some method you called. And it might have already been resolved, or it might be still pending. Now you call the promise's then method, and you can know: it will be asynchronous. You don't need to deal with cases that might be synchronous or not and change the meaning of your code, it simply is always asynchronous.

Categories

Resources