We need to write a Node.js function that polls a certain API endpoint for a result of a previously requested calculation. The result takes a random time to be generated and may not me generated at all. We'd like to get it as soon as possible, but also I don't want to wait for too long, which means that after a certain number of API calls we'd like the function to fail (reject a Promise).
There is one way communication between our code and the API.
const Bluebird = require('bluebird');
function getResult() {
return new Bluebird(async function (resolve, reject) {
let counter = 0;
while (counter < 10) {
await Bluebird.delay(1000);
const res = await apiCall();
if (res.data) {
resolve(res.data);
} else {
counter += 1;
}
}
reject('timeout');
});
}
Is this the correct approach?
No. This is the async/await version of the Promise
constructor antipattern! It won't even stop the loop when you call resolve
, or reject when an exception is thrown (e.g. when res
is null
).
You should use
async function getResult() {
for (let counter = 0; counter < 10; counter += 1) {
await Bluebird.delay(1000);
const res = await apiCall();
if (res.data) {
return res.data;
}
}
throw new Error('timeout');
}
If you want to ensure that a Bluebird promise is returned, not a native one, wrap it in Bluebird.method
or tell your transpiler to use Bluebird.