Home > Net >  await a new Promise in an async function
await a new Promise in an async function

Time:04-23

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 it return it immediatly?
  • if there is no await, should this function be marked as async?
  • 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 as async?

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.

  • Related