When Is the Body of a Promise Executed

When is the body of a Promise executed?

Immediately, yes, by specification.

From the 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)

This is defined in the ECMAScript specification (of course, it's harder to read...) here (Step 9 as of this edit, showing that the executor is called synchronously):


  1. Let completion be Completion(Call(executor, undefined, « resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]] »)).

(my emphasis)

This guarantee may be important, for example when you're preparing several promises you then pass to all or race, or when your executors have synchronous side effects.

Why do promises execute at the point of declaration?

Thinking of promises as "executing" is getting you confused. A promise is purely a notification mechanism. It is typically tied to some underlying asynchronous operation and when you create the promise, the asynchronous operation is typically started.

Promise.all() is then used to track when a whole bunch of asynchronous operations that you've already started have completed (or ended with an error).

So, you don't use Promise.all() to start a bunch of things. You use it just to track when they are all done and they are started elsewhere in your code.


When you manually create a promise with new Promise(), the promise executor is executed immediately. That's how they are designed.

If you had real asynchronous operations in your promise executor and you were doing console.log() when those operations completed, you'd probably not find any issue with how promises are designed. I think most of your confusion stems from the fact that you don't actually have any asynchronous operation inside your promise executor and thus there's really no reason to even use a promise for that. Promises are designed to track the completion of asynchronous operations. No reason to use them if you don't have an actual asynchronous operation.

FYI, if you want to start some asynchronous operation at some time in the future from inside the promise executor, you can use the normal setTimeout() or process.nextTick() or setImmediate() operations to schedule the operation to start later.

would have expected output to have been

Plus, it appears you are expecting your output to be in a strict order. Promise.all() expects there to be N asynchronous operations running in parallel and there is no guaranteed order of completion for those N operations. Instead, Promise.all() will track them all, collect all the results and present the .then() handler with an array of results in order (if they all resolved successfully). It does not run the operations themselves in order. The operations run in parallel and complete in whatever natural order they take.

Javascript Promise Callback (when it is called)

The promise executor function is called immediately by the promise constructor. That's how it works. The usual point of that executor function is to initiate your asynchronous operation and then later when that asynchronous operation completes, you call resolve() or reject().

Here's an example of putting the plain callback version of fs.readFile() in a promise wrapper:

function readFilePromise(filename, options) {
return new Promise((resolve, reject) => {
fs.readFile(filename, options, (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
})
});
}

Usage:

 readFilePromise("myfile.txt").then(data => {
console.log(data);
}).catch(err => {
console.log(err);
});

Note: This is just an example for illustration here. Nodejs now already has promisified versions of fs.readFile called fs.promises.readfile, but this structure can be used when you need to manually promisify other more complicated things that don't have their own promise interface yet.


For a real world example of promisifying something more complicated see the mapConcurrent() function here or the rateLimitMap() function here.

JavaScript: Promise callback execution

The promise executor function is the function you pass to new Promise. It is executed synchronously so it can start whatever asynchronous process the promise represents.

The callbacks you attach with then, catch, and finally are always called asynchronously, whether the promise is already settled or not.

So in your example, console.log("After resolving the promise"); is called before the console.log you've passed to then.

Here's an example showing that more clearly:

let myPromise = new Promise((resolve, reject) => {    console.log("In the executor function");    resolve("Resolved from the promise");});myPromise.then(result => {    console.log("In the fulfillment handler: " + result);});
console.log("After resolving the promise");

Why does my Promise definition gets executed?

That is simply how promises are defined. They run their executor function immediately. It's in the spec: Promise(executor), step 9.

This is an instance of the revealing constructor pattern; reading that might help you understand.



Related Topics



Leave a reply



Submit