Why does the Promise constructor require a function that calls ‘resolve’ when complete, but ‘then’ does not – it returns a value instead?

Bergi’s answer is excellent, and has been very helpful to me. This answer is complementary to his. In order to visualize the relationship between the Promise() constructor and the then() method, I created this diagram. I hope it helps somebody… maybe even me, a few months months from now.

The main idea here is that the “executor” function passed to the Promise() constructor sets tasks in motion that will set the state of the promise; whereas the handlers you pass to then() will react to the state of the promise.

Diagram: Promise() executor vs. then() method
(Code examples adapted from Jake Archibald’s classic tutorial.)

This is a highly simplified view of how things work, leaving out many important details. But I think if one can keep a grip on a good overview of the intended purpose, it will help avoid confusion when one gets into the details.

A couple of selected details

The executor is called immediately

One important detail is that the executor function passed to the Promise() constructor is called immediately (before the constructor returns the promise); whereas the handler functions passed to the then() method will not be called till later (if ever).

Bergi mentioned this, but I wanted to restate it without using the terms a/synchronously, which can be confused if you’re not reading carefully: The distinction between a function calling something asynchronously vs. being called asynchronously is easy to gloss over in communication.

resolve() is not onFulfill()

One more detail I’d like to emphasize, because it confused me for a while, is that the resolve() and reject() callbacks passed to the Promise() constructor’s executor function are not the callbacks later passed to the then() method. This seems obvious in retrospect, but the apparent connection had me spinning in circles for too long. There is definitely a connection, but it’s a loose, dynamic one.

Instead, the resolve() and reject() callbacks are functions supplied by the “system”, and are passed to the executor function by the Promise constructor when you create a promise. When the resolve() function is called, system code is executed that potentially changes the state of the promise and eventually leads to an onFulfilled() callback being called asynchronously. Don’t think of calling resolve() as being a tight wrapper for calling onFulfill()!

Leave a Comment