Reputation: 1545
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:
Upvotes: 0
Views: 270
Reputation: 19301
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:
chain
after constructing it in its entirety before returning chain
from the first then handler.then
success handler and use it being called to indicate objectDetail
contains valid data, orCreate 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.
Upvotes: 1
Reputation: 370749
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)
))
));
Upvotes: 5