Javascript Promise Inside Async/await Function Resolve Final Array Of Responses
Solution 1:
This is a bit untested
const api_url = 'https://some_url.com/api/data';
get_data(api_url).then((results) => {
console.log(results);
}).catch((error) => {
// console.error(error);
});
functionget_items (url) {
const options = {
baseURL: url,
method: 'get'
};
returnaxios(options).then((response) => response.data);
}
asyncfunctionget_data(next_url) {
const output = [];
while (next_url) {
const { results, next } = awaitget_items(next_url);
output.push(...results);
next_url = next;
}
return output;
}
Basically it makes things a bit neater. I suggest to look at more examples with Promises and the advantage and when to ease await/async. One thing to keep in mind, if you return a Promise, it will follow the entire then
chain, and it will always return a Promise with a value of the last then
.. if that makes sense :)
Solution 2:
There are a few problems. One is that you never resolve
the initial Promise
unless the else
block is entered. Another is that you should return the recursive get_data
call every time, so that it can be properly chained with the initial Promise
. You may also consider avoiding the explicit promise construction antipattern - get_items
already returns a Promise
, so there's no need to construct another one (same for the inside of get_items
, axios
calls return Promise
s too).
You might consider a plain while
loop, reassigning the next_url
string until it's falsey:
functionget_items (baseURL) {
const options = {
baseURL: url,
method: 'get'
}
// return the axios call, handle errors in the consumer instead:returnaxios(options)
.then(res => res.data)
}
asyncfunctionget_data() {
const output = []
let next_url = 'https://some_url.com/api/data'try {
while (next_url) {
const response = awaitget_items(next_url);
output.push(...response.results)
next_url = response.next;
}
} catch (e) {
// handle errors *here*, perhapsconsole.log(e)
}
return output;
}
Note that .catch
will result in a Promise
being converted from a rejectedPromise
to a resolved one - you don't want to .catch
everywhere, because that will make it difficult for the caller to detect errors.
Solution 3:
Another way of doing it is to not use async at all and just recursively return a promise:
constgetItems = (url) =>
axios({
baseURL: url,
method: 'get',
}).then((response) => response.data);
constgetData = (initialUrl) => {
constrecur = (result, nextUrl) =>
!nextUrl
? Promise.resolve(result)
: getItems(nextUrl).then((data) =>recur(result.concat([data.results]), data.next),
);
returnrecur([],initialUrl)
.catch(e=>Promise.reject(e.stack));//reject with error stack
};
As CertainPerformance noted; you don't need to catch at every level, if you want getData to reject with error.stack you only need to catch it once.
However; if you had 100 next urls and 99 of them were fine but only the last one failed would you like to reject in a way that keeps the results so far so you can try again?
If you do then the code could look something like this:
constgetData = (initialUrl) => {
constrecur = (result, nextUrl) =>
!nextUrl
? Promise.resolve(result)
: getItems(nextUrl)
.catch(e=>Promise.reject([e,result]))//reject with error and result so far
.then((data) =>recur(result.concat([data.results]), data.next),
);
returnrecur([],initialUrl);//do not catch here, just let it reject with error and result
};
Post a Comment for "Javascript Promise Inside Async/await Function Resolve Final Array Of Responses"