"Utilize a series of Promise chains within a Promise's then

I am trying to retrieve an array list of object IDs from an API using axios. Once I have the object ID list, I want to fetch the details of each object using promises.

This is what I have in mind:

var objectDetail = [];

axios.get('apiendpoint/')
.then((response) => {
  var listOfObjectIds = response.data;
  var chain = Promise.resolve();
  for (var objectId of listOfObjectIds) {
    chain = chain.then(axios.get(`apiendpoint/${objectId}`)
      .then((response) => {
        objectDetail.push(response.data);
      })
    );
  }
  return chain;
}).then((chain) => {
  console.log(chain);
  return chain;
})

The code above is returning undefined as the promise chain object is not being passed to the then method call. I'm wondering if my approach is incorrect or if there's something I'm overlooking. Thank you.

Here are some related articles that I've come across:

  • How to loop dynamically over multiple promises in a for loop while using fetch?
  • Creating a promise chain in a for loop

Answer №1

The promise chain is being passed to the final .then, however, it is not returning any value. Take a look at your:

.then((response) => {
  objectDetail.push(response.data);
})

The above function does not return anything. If you intend to use objectDetail at the end of the chain without relying on an external variable, make sure to also include a return statement:

.then((response) => {
  objectDetail.push(response.data);
  return objectDetail;
})

Keep in mind that

}).then((chain) => {
  console.log(chain);
  return chain;
})

may be unnecessary - unless you are simply logging the result. In that case, it might be better to omit this step altogether.

If clarity is what you seek, consider using Promise.all instead:

axios.get('apiendpoint/')
  .then(({ data }) => Promise.all(
    data.map(objectId => (axios.get(`apiendpoint/${objectId}`)
      .then(res => res.data)
    ))
  ));

Answer №2

In order to meet a promise, it cannot be fulfilled by another promise. If a promise is returned within a then( onfulfilled) handler, the code will wait for this returned promise to be resolved or rejected before moving on to the next promise in the chain using the outcome of the previously returned promise.

Thus,

//...
  return chain;
}).then((chain) => {
  console.log(chain);
  return chain;
})

This can be confusing - the promise named chain that is returned initially from the first line does not get passed to the subsequent then handler. Instead, what gets passed is the value of the last successfully completed promise within the chain. However, if no value is explicitly returned within the handlers for chain, it remains as undefined.

There are several options to address this:

  • For debugging purposes, you can choose to log the value of chain after fully constructing it, just before returning chain from the initial then handler.
  • You could also disregard the actual value being passed to the final success handler and interpret its invocation as an indication that objectDetail has valid data inside,
  • Create objectDetail within the first then handler and have it returned by promises added to chain during the construction phase.

    axios.get('apiendpoint/')
    .then((response) => {
        var listOfObjectId = response.data;
        var objectDetail = [];
        var chain = Promise.resolve()
        for (var objectId of listOfObjectId) {
            chain = chain.then(axios.get(`apiendpoint/${objectId}`)
            .then((response) => {
                objectDetail.push(response.data);
                return objectDetail; // return details array
            });
        }
        return chain;
    })
    .then( objectDetail) => {
        // process objectDetail
    })
    .catch(err=> console.log(err););
    

The above method handles detail requests in a sequential manner. For parallel issuance of these detail requests, consider rewriting it using Promise.all.

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

Is it possible for me to sum up each row in the table and then deactivate it using a checkbox?

I am facing an issue with my code. The problem arises when I utilize the each() function; it iterates from the first cell to the end of the row, fetching every value along the way. What I actually want is for it to retrieve the value from each row individu ...

Dynamic filtering with Javascript

I am searching for inspiration on how to create a filter in the left sidebar that dynamically updates the page content when clicked, and if there are subcategories, displays them below the selected filter in the sidebar. I've discovered that AJAX is ...

From milliseconds to hours: a straightforward conversion

Given a start date, time and end date, time, I am trying to calculate the total travel duration. The output is in milliseconds and needs to be converted into hours format. Despite attempting some solutions shared here, I haven't been successful. < ...

Remove multiselect label in PrimeNG

I am attempting to change the multiselect label of selected items and replace it with a static default label. Here is what it currently shows: https://i.sstatic.net/qBNHG.png This is what I have tried: .p-multiselect-label { visibility: collapse; ...

Is it mandatory to employ the spread operator in the process of updating an object while using the useState hook?

Recently delving into hooks, I stumbled upon an insightful passage in the official documentation regarding Using Multiple State Variables: It is noteworthy that updating a state variable in hooks replaces it entirely, as opposed to merging it like in th ...

Ensure all division elements have the same height by utilizing a directive

My webpage currently displays a grid that is not properly arranged. However, when I executed the code below in the console, the grid was formatted correctly: var maxHeight = Math.max.apply(null, $("#activityfeeddetails").find(".course_thumb_outer").map(fu ...

What is the best way to load content into Bootstrap tabs?

I would like to incorporate a loading spinner within the bootstrap tabs. When a user clicks on a tab pane link, a loading spinner will be displayed for a few seconds before showing the actual tab content. HTML : <ul class="nav nav-tabs" id=&q ...

The database is failing to reflect any changes even after using the db.insert function

I am currently working on implementing a forgot password feature in my express app using the node mailer package. This functionality involves sending a new password to the user's email and then updating the database with the new password. However, I h ...

When using Laravel 5.2, JSON data is mistakenly returned as HTML

I've encountered an issue with ajax. My goal is to fetch all the records from a specific table using this ajax call: $('#chooseInvBtn').on('click', function(){ $.ajax({ type: "POST", url ...

Information is inaccessible beyond onBeforeMount in the Composition API of Vue 3

In my code snippet block, I have the following code: <script setup lang="ts"> import ApiService from '../service/api' import { reactive, onBeforeMount } from 'vue' let pokemons = reactive([]) onBeforeMount(async ()=> ...

Is it possible to eliminate the css class prefix when using Modular css in React?

When working with React & NextJS, I have observed that my modular SCSS files are automatically prefixing my classnames with the name of the file. Is there a way to turn off this feature as it is making the DOM structure difficult to interpret? For instanc ...

Do not allow the use of <p> or <br> tags in

I would like to enable basic styling with <strong>, <em> and lists using ckeditor. But I do not want any <br> or paragraph tags because I normalize my content and prefer it to be clean. After some research online, I came across this sol ...

Spin the Three.js camera in a circular motion along the Y-axis

I'm feeling a bit puzzled about this one :S I've written a code that allows my camera to rotate only halfway. I can move the camera along half of a circle using mousemove events, but I actually want it to be able to complete a full rotation :) ...

Error encountered in Express middleware: Attempting to write private member #nextId to an object that was not declared in its class

Currently, I am in the process of developing a custom logger for my express JS application and encountering an issue. The error message TypeError: Cannot write private member #nextId to an object whose class did not declare it is appearing within my middle ...

The unusual spinning behavior of child elements in three.js

My current project involves implementing an experimental version of a 2x2x2 Rubik's Cube. I have gathered insights from two previous posts that addressed issues related to attaching and detaching child objects in Three.js: Three.js: Proper way to add ...

Identifying the Source of a Page Redirection in Javascript: A Step-by-Step Guide

After downloading a free template from the internet, I noticed that there was a link back to the website in the footer. Upon attempting to remove this link, my page started redirecting to the homepage URL of the original website. How can I pinpoint which ...

What is the process of rotating a vector by 90 degrees to align it with a perpendicular plane, and then adjusting it further by 15 degrees out of

My ultimate objective is to determine a vector that represents the direction of the green line depicted in the image below, based solely on the positions of the yellow and green dots. To clarify, the angle of the vector can vary as long as its endpoint ...

Deployment replacement in Kubernetes encounters error

I've developed a NodeJS script to deploy review apps to Kubernetes for my GitLab repository, using the Kubernetes NodeJS client. Including abbreviated definitions of Kubernetes resources for thoroughness: const k8s = require('@kubernetes/client ...

Uncertain about the best way to utilize an observable

I am currently developing a real-time chat application using Angular and Node.js. The backend is powered by nodejs and I am utilizing socket.io for communication. Server Side io.on('connection', (socket) => { socket.on('new-message&apo ...

Unable to successfully create a dynamic anchor tag and open it in a new tab

I am receiving a PDF link in an AJAX response and I would like to manually trigger the download. Here is the code that I am currently using: var fileLink = document.createElement('a'); fileLink.href = responseData.PDF_LINK; fileLink.setAttribute ...