Is this an anti-pattern for using async / await inside the new Promise () constructor?
I use a function async.eachLimit
to manage the maximum number of operations at a time.
const { eachLimit } = require("async");
function myFunction() {
return new Promise(async (resolve, reject) => {
eachLimit((await getAsyncArray), 500, (item, callback) => {
// do other things that use native promises.
}, (error) => {
if (error) return reject(error);
// resolve here passing the next value.
});
});
}
As you can see, I cannot declare the function myFunction
as async because I have no access to the value in the second callback of the function eachLimit
.
You are effectively using promises inside a promise constructor executor function, so this is the anti-pattern of the Promise pattern .
Your code is a good example of a basic risk: Don't propagate all bugs safely. Read why there .
Also, using async
/ await
can make some more surprises. For comparison:
let p = new Promise(resolve => {
""(); // TypeError
resolve();
});
(async () => {
await p;
})().catch(e => console.log("Caught: " + e)); // Catches it.
with a naive (wrong) equivalent async
:
let p = new Promise(async resolve => {
""(); // TypeError
resolve();
});
(async () => {
await p;
})().catch(e => console.log("Caught: " + e)); // Doesn't catch it!
Look in your browser for the web console for the latter.
The first one works because any immediate exception in the executor function of the Promise constructor conveniently rejects the newly constructed promise (but inside any, .then
you're on your own).
The second doesn't work because any immediate exception in the function async
rejects the implicit promise returned by the function itself async
.
Since the return value of the promise executor function is not used, this is bad news!
Your code
There is no reason why you cannot define myFunction
how async
:
async function myFunction() {
let array = await getAsyncArray();
return new Promise((resolve, reject) => {
eachLimit(array, 500, (item, callback) => {
// do other things that use native promises.
}, error => {
if (error) return reject(error);
// resolve here passing the next value.
});
});
}
Though why use legacy concurrency management libraries when you have one await
?
source to share