DEV Community

Vasil Vasilev
Vasil Vasilev

Posted on

How the `.then()` method interacts with the JavaScript event loop.

Async via Web APIs

Why do we need them? So that we can have non-blocking operations. We have our code and javascript executes synchronously so what if we need to fetch some data on a remote server. Execution stops until the data is fetched. That is hardly efficient. We rely on the Javascript environment that gives us Web APIs to make async non-blocking operations possible. One popular option to do this fetching of data and no block the main thread is via Fetch API. But what actually happens underneath.

Promises

To understand what happens underneath, I will use a more simple API -> setTimeout in conjunction with Promise, since the same process is relevant for any other Web API. We rely on setTimeout to extract the callback we pass into it from the call stack (main thread) so as to not block it until some moment in the future (with setTimeout we know the minimum amount of time this moment will expire in).

Consider the following example for any future reference:

new Promise((resolve) => {
    setTimeout(()=>resolve('Done!'), 100);
})
    .then(result => console.log(result))
Enter fullscreen mode Exit fullscreen mode

The function we pass into the setTimeout is actually the resolve of a Promise. So, in effect, we want the promise to be resolved after the setTimeout is executed (meaning being extracted from the main thread, set as a macroTask, await the clearing up of the main thread and finally re-introduced and executed in the main thread). To truly understand Promises, you have to understand the connection between resolve and .then().

Image description

[[PromiseFulfillReactions]]

Promises in JavaScript represent an eventual completion (or failure) of an asynchronous operation and its resulting value. The [[PromiseFulfillReactions]] and [[PromiseRejectReactions]] are internal properties of a Promise that hold the functions (handlers) to be executed when the Promise is fulfilled or rejected.

The [[PromiseFulfillReactions]] has among others a PromiseReaction field with [[Handelers]], meaning what we put in the .then(). This field gets triggered when the promise is fulfilled. When does the promise get fulfilled -> when the acync operation that was in the task Queue gets pack in the call stack and is executed.

So basically, we have an async operation (setTimeout), that async operation has the resolve of the Promise. When the async operation gets back into the call stack and gets executed, the resolve of the promise gets executed.
Namely, the Promise becomes fulfilled and it triggers the PromiseFullfillReaction Handler (which is the code inside .then()). result => console.log(result) is set onto the microTask Queue until the call stack is free and when it is free, it finally gets the actual parameter 'Done!' applied to be executed.

Top comments (0)