I have an async-based code base, and I need to interact with some "callback based" external libraries.
I though I could wrap the external library with a Promise
that could act as a "bridge" and offer me an async facade.
I ended up with a doubt about how to define this wrapper.
In code:
export function externalApi(onsuccess: (response: string) => void): void {
// stuff
onsuccess('response');
}
export async function myWrapper(): Promise<string> {
return await new Promise((resolve) => externalApi(resolve));
}
My doubts are
- should
myWrapper
await
the promise? or should itreturn
it immediatly? - if there is no
await
, should this function be marked asasync
? - are there some penalties writing this
await new Promise(...)
stuff?
CodePudding user response:
should
myWrapper
await
the promise? or should it return it immediatly?
That's up to you. Doing return await
at the top level of an async
function isn't necessary,¹ but might make async stack traces clearer by including the async
function in the async stack trace. So you might keep it for that reason, or you might remove it for that reason. :-) (I should note that with the latest V8, I can no longer see a difference in the stack traces, both include the wrapper function. So things may have moved on in that regard; I know async stack traces were a hot development area for a while.)
if there is no
await
, should this function be marked asasync
?
No, if you remove the await
, there's no reason for it to be async
.
are there some penalties writing this await new Promise(...) stuff?
If you mean specifically the await
in the return await
, then no, not when the promise you're using await
on is a native promise. It used to introduce a (largely harmless) async tick into the settlement of the async
function's promise, but the spec was updated to allow engines to avoid it.
¹ Using return await
not at the top level of an async
function is necessary if you want to catch the rejection of the promise in the function, or you want to do something in a finally
clause, or something like that — anything where the async
function's logic relies on that promise being settled before the async
function itself returns. For instance, you'd need it here:
async function example() {
try {
return await somethingThatProvidesAPromise();
} catch (e) {
throw new WrapperError(e);
}
}
and here
async function example() {
const lock = acquireLock();
try {
return await doSomethingWith(lock);
} finally {
releaseLock(lock); // (Where `releaseLock` guarantees it nevers throws)
}
}
Neither of those would be correct without the await
.