Unraveling the Inner Workings of Promise Chaining

Currently, I am diving into the world of promise chaining and have encountered a question. Let's take a look at this example with a promise chain:

const myPromise = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve("foo");
    }, 10000);
});

myPromise
    .then(handleFulfilledA, handleRejectedA)  // first then
    .then(handleFulfilledB, handleRejectedB)  // second then
    .then(handleFulfilledC, handleRejectedC); // third then

After creating the myPromise object using the promise constructor, the handlers handleFulfilledA and handleRejectedA are connected to it. Due to the 10-second delay in resolving myPromise, the second and third then methods will be executed before the resolution.

So, what really happens behind the scenes when encountering the second and third .then method?

I tried to research and found that each then call generates a new Promise object - let’s name them promiseB and promiseC. The handlers handleFulfilledB and handleRejectedB are associated with promiseB, while handleFulfilledC and handleRejectedC are linked to promiseC.

However, if this is accurate, how exactly do the original reaction handlers (handleFulfilledA, handleRejectedA) from myPromise recognize they need to interact with promiseB? In essence, how is the bridge between these handlers and the subsequent promises established?

Answer №1

According to the MDN documentation regarding the functionality of the then method:

The then() function creates a new promise object while also modifying the original promise object by adding handlers to an internal list. This means that the handler remains associated with the original promise and will exist for at least as long as the original promise.

This clarification helps in understanding how chaining is achievable.

Answer №2

When myPromise is fulfilled and its [[PromiseFulfillReactions]] are executed, how will handleFulfilledA and handleRejectedA know to resolve or reject promiseB?

handleFulfilledA and handleRejectedA do not directly control the resolution or rejection of promiseB.

The outcome of promiseB depends on two factors:

  • What occurs with the original promise, myPromise, and
  • What actions are taken within the fulfillment/rejection handler

In your code, when myPromise is resolved, handleFulfilledA is invoked. The fate of promiseB hinges on the actions performed inside this handler; it may either be resolved or rejected accordingly.

If a non-promise value is returned, or if undefined is implicitly returned, promiseB will be fulfilled with that particular value. Likewise, if an error is thrown within the fulfillment handler of myPromise, promiseB will be rejected with that error as the reason for rejection.

What happens if a promise is returned from the fulfillment handler? In such cases, promiseB will be resolved with that promise. This signifies that the destiny of promiseB relies on the promise returned by the fulfillment handler of myPromise. PromiseB will be fulfilled if the promise returned by the then handler resolves, and it will be rejected if the promise returned by the then handler is rejected.

The provided code example illustrates how the outer promise (promiseB) can resolve to the inner promise returned by the then handler:

const outerPromise = new Promise((resolveOuter, rejectOuter) => {
   const innerPromise = new Promise((resolveInner, rejectInner) => {
      // ...
   });

   innerPromise.then(resolveOuter, rejectOuter);
});

Recommended reading: Understanding Javascript promises in detail

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Transferring information from Console to a web address

Every time I click on a button, the correct data appears in the console. However, now I want the data 'reid' to be passed to the URL when the button is clicked. When I attempt it using: this.router.navigateByUrl('/details/' + this.resu ...

Discovering the right place to establish global data in Nuxt JS

Exploring the world of NuxtJS today, I found myself pondering the optimal method for setting and retrieving global data. For instance, how should a frequently used phone number be handled throughout a website? Would utilizing AsyncData be the most effecti ...

Creating a custom AngularJS filter to search within an array of objects

I'm currently working with an object in my project: {"A":[],"B":[],"C":[],"D":[],"E":[],"F":[{"name":"Fargo","id":29}],"G":[],"H":[],"I":[],"J":[],"K":[],"L":[],"M":[],"N":[],"O":[],"P":[],"Q":[],"R":[],"S":[{"name":"Sullivan","id":23},{"name":"Sven" ...

Having trouble with the menu toggle button on Bootstrap 4?

When using Bootstrap 4, the breadcrumb button may not function properly when the header becomes responsive. I have ensured that Bootstrap 4 CSS and JS are included in the project. Please assist me in resolving this issue. Code: .navbar { height:100 ...

Excessively Running Firebase Function Due to setInterval Usage

My Firebase function is set to run every 20 minutes using setInterval, but it seems to be executing more frequently than expected. Here is an excerpt from my code: try { const response = await axios.get( "https://ll.thespacedevs.com/2.0.0/ ...

Image Carousel Extravaganza

Trying to set up a sequence of autoplaying images has been a bit of a challenge for me. I've attempted various methods but haven't quite nailed it yet. Take a look at what I'm aiming for: https://i.stack.imgur.com/JlqWk.gif This is the cod ...

Refreshing CKFinder Form Field with jQuery

Looking to update the value of an input field .ckfinder-input using CKFinder's pop-up image selector. Everything runs smoothly until attempting to assign the selected image URL to the input field with input.val() = fileUrl, resulting in the error mess ...

Tips for real-time content updates on a server-side rendered express application

My social media app, built using Express, Pug, and JavaScript for server-side rendering, is fully functional. However, whenever I comment on a post, I need to manually reload the page to see the new comment displayed. I'm exploring ways to dynamicall ...

What is the reason for the error that Express-handlebars is showing, stating that the engine

I recently added express-handlebars to my project and attempted the following setup: const express = require("express"); const exphbs = require('express-handlebars'); const app = express(); app.engine('.hbs', engine({defaultL ...

Looking to convert an empty star glyphicon button into a star glyphicon button when clicked using JavaScript?

Is there a way to make the glyphicon change when clicking on the button instead of the glyphicon itself? <script> $('.btn').click(function(){ $(this).find('.glyphicon').toggleClass('glyphicon-star-empty glyphico ...

Issue: It is not possible to display a <Router> within another <Router>. It is important to only have one router in your application

An error is occurring in my React application because I have nested routers. I need to use a second router in Navbar.js for the <Link> component to work. Currently, I have React Router implemented in two different files, and if I remove one of them, ...

Utilizing diverse values retrieved from HTML data attributes

*UPDATE Within my HTML, I have a list titled "#wordlist" that contains the words for my game, along with corresponding audio and images for each word. Everything is functioning correctly. As there will be multiple versions of the game, I've been tas ...

How can you reach a constant from a different component in React?

I am new to developing a react application and struggling with accessing const data from another component. The specific constant I need access to is located in the TableComponent.js file. TableComponent.js export default function({ infinite }) { const [ ...

The redirection of the URL after form submission is not functioning correctly

I'm attempting to develop a pair of dropdown lists in Elementor where the second dropdown's options depend on what is selected in the first, and the second contains URLs linked to a GO button that redirects to the chosen URL. However, I've f ...

Is there a way to retrieve the xpath count in Selenium WebDriver through Jasmine JavaScript?

var elementCount = browser.findElements(driver.By.xpath('//somenode')).getXpathCount(); console.log( elementCount.intValue() ); Whenever I try to print the count, I encounter this error: Error occurred - TypeError: undefined is not a function ...

What is the best way to fetch multiple values using momentjs from firebase?

After fetching data from Firebase and storing it in an array, I am attempting to retrieve the posted_at values (timestamp of when something was posted) in a time format using Vuejs. However, I am facing difficulty as it only retrieves a single value instea ...

Accessing stored web pages / Browser as an interactive interface

I have a couple of questions I need help with. The first one is about how to open a saved HTML file in a browser without an internet connection. Next, I'm looking for advice on using the browser as a user interface for a desktop image viewing program ...

Creating elegant Select Dropdown Box in AngularJS without relying on images

I am currently working on an angular page and have implemented a dropdown with ng-Options to fetch and set values successfully. However, I am now looking to enhance the appearance of this dropdown. After exploring options like ui-select, I realized that be ...

Automatically sort with Angular and PHP

Currently, I am in the process of getting a search function to work smoothly. It involves loading data from a database using PHP to Angular, and everything seems to be displaying correctly prefilled, with one exception. There is a select option where the ...

What is the method for triggering a JavaScript function without submitting the form when pressing Enter in a text input field?

Is there a way to trigger a function in JavaScript when the enter key is pressed in an input field without submitting the form? I'm looking for a solution where pressing the enter key in an input text field only calls the function detect_enter_keyboa ...