Reputation: 109
I have an asynchronous function 'doApiRequest' that is called inside of a 'then' function...
doSomething()
.then(() => {
return doApiRequest();
})
.then((apiResult) => {
doSomethingElse(apiResult);
});
The issue being that doApiRequest returns a Promise with the eventual result of that API request. However, do to the nature of the API I'm working with there is a request rate limit involved. I plan on handling that by having each API request add itself to a queue, and then when the queue releases the request after waiting for the rate limit, the API request will finish resolving. While I could do something like...
doSomething()
.then(() => {
return waitForRateRefresh();
})
.then(() => {
return doApiRequest();
})
.then((apiResult) => {
doSomethingElse(apiResult);
});
I may end up having many 'doApiRequest' calls, so having to chain a 'waitForRateRefresh' on each seems like a bad method and I'd also have to make it work so it can pass along the data from previous then statements. What I'd like to do is handle this inside of 'doApiRequest' itself.
'doApiRequest' would look something like this
doApiRequest(){
return new Promise((resolve, reject) => {
waitForRateRefresh().then(() => {
//http call
resolve(someValue);
};
});
}
However I'm trying to find a way to do this that doesn't involve nesting Promises. What other ways would there be to go about this. Another way I've though of doing it is by using Async/Await instead, is there any other way of doing it with just promises? What happens (or is it even possible) to return a Promise with an attached then function from 'doApiRequest' like...
return waitForRateRefresh().then(() => new Promise(..../http call));
In the original then function where 'doApiRequest' is called - will it receive the value returned by 'waitForRateRefresh', or the result of traversing down the then chain attached to it.
Thanks for any insights
Upvotes: 0
Views: 7333
Reputation: 1
While async/await is great, if you're using an older version of nodejs that doesn't support it, then you'll either need to transpile async/await
code, or use plain ol' Promises
Don't know if you've ever seen transpiled async
/await
- it's quite "verbose"
What you can do, assuming you actually want to pass the result of doSomething
to doApiRequest
is this
doSomething()
.then(result => waitForRateRefresh().then(() => result))
.then((doSomethingResult) => doApiRequest(doSomethingResult))
.then((apiResult) => doSomethingElse(apiResult));
of course, the above can be simplified to
doSomething()
.then(result => waitForRateRefresh().then(() => result))
.then(doApiRequest)
.then(doSomethingElse);
To clarify a point about promise constructor anti-pattern
doApiRequest(){
return new Promise((resolve, reject) => {
waitForRateRefresh().then(() => {
//http call
resolve(someValue);
};
});
}
this is simplified to
doApiRequest(){
return waitForRateRefresh().then(() => {
//http call
return someValue;
};
}
Of course, if // http call
is asyncrhonous, then return someValue
can't be used like that. But that would be the case for your version of the code as well
To accept a value from doSomething in this version of doApiRequest, change the code to
doApiRequest(someResult){
return waitForRateRefresh().then(() => {
//http call - use someResult here
return someValue;
};
}
The main code is now
doSomething()
.then(doApiRequest)
.then(doSomethingElse);
Again, though ... the //http call
and return someValue
will not work as desired if someValue
is gathered asynchronously in whatever http call
is
and one more idea so you don't need to rewrite existing functions
create a "wrapper" around doApiRequest
const qApiRequest = result => waitForRateRefresh().then(() => doApiRequest(result));
now, the code is
doSomething()
.then(qApiRequest)
.then(doSomethingElse);
Of course, with async
/await
it's just
const doSomethingResult = await doSomething();
await waitForRateRefresh();
const apiResult = doApiRequest(doSomethingResult);
const finalResult = doSomethingElse(apiResult);
Of course, these would need to be inside a function tagged async
Upvotes: 6
Reputation: 5472
I would use async/await
, it keeps the code very readable and makes it easy to reason what is happening next.
await doSomething();
await waitForRateRefresh();
const apiResult = await doApiRequest();
await doSomethingElse(apiResult);
Upvotes: 2