简体   繁体   中英

return Promise chain inside Promise then

I want to fetch API using axios that return array list of objectId. After I get the list objectId I want to fetch the detail of the object using promise

I think of something like this

var objectDetail = [];

axios.get('apiendpoint/')
.then((response) => {
  var listOfObjectId = response.data;
  var chain = Promise.resolve()
  for (var objectId of listOfObjectId) {
    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 returns undefined, the promise chain object is not passed to then method call. Is my approach wrong or am I missing something? thank you

Here are some stack I have read, might be related:

The promise chain is being passed to the final .then , but the promise chain isn't returning anything : see your

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

That function doesn't return anything. If you wanted to use objectDetail at the end of the chain without referencing the outer variable, return it as well:

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

But note that

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

is a bit redundant - unless you're only doing that in order to log the result, better just to leave it off entirely.

Your code would be clearer if you used Promise.all instead:

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

You can't fulfill a promise with a promise. If you return a promise from within a then( onfulfilled) handler, promise code waits for the returned promise to be settled before resolving or rejecting the next promise in a chain with the success or failure value of the returned promise.

So

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

is confusing - the chain promise returned in the first line is not passed to the next then handler. What is passed is fulfilled value of the last promise in chain after it completes successfully. However, since handlers within chain don't explicitly return a value, this will be undefined .

Options include:

  • For debugging purposes, optionally log the value of chain after constructing it in its entirety before returning chain from the first then handler.
  • Ignore the actual value passed to the final then success handler and use it being called to indicate objectDetail contains valid data, or
  • Create objectDetail in the first then handler and return it from promise handlers added to chain during construction.

     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 method above processes detail requests sequentially. It could be rewriten using Promise.all for detail requests to be issued in parallel.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM