Javascript – How do JavaScript engines convert async/await to promises under the hood

asyncjavascriptlanguage-discussionpromises

I'm curious how the async/await syntax is converted to Promises. Maybe I'm just not thinking about it properly, but I don't know how this code would be converted to a Promise:

async function myFunc(doAwait) {
    doSomething();
    if (doAwait) {
        await doSomethingAsync();
    }

    return doSomethingElse();
}

When doAwait is false, I'd expect this function to run equivalent to:

return new Promise(res => {
    doSomething();
    res(doSomethingElse());
});

If it's true, it would be:

return new Promise(() => { doSomething(); })
    .then(() => doSomethingAsync())
    .then(() => doSomethingElse());

It could do something like:

let p = new Promise(() => { doSomething(); });
if (doAwait) {
    p = p.then(() => doSomethingAsync());
}
return p.then(() => doSomethingElse());

But that introduces an extra, possibly unnecessary then. Maybe that's just unavoidable.

Best Answer

This async/await code:

async function myFunc(doAwait) {
    doSomething();
    if (doAwait) {
        await doSomethingAsync();
    }

    return doSomethingElse();
}

Would be basically equivalent to this:

function myFunc(doAwait) {
    doSomething();
    if (doAwait) {
        return Promise.resolve(doSomethingAsync()).then(doSomethingElse);
    }

    return Promise.resolve(doSomethingElse());
}

For complete equivalence, including synchronous exceptions in any of the functions calls, it would be something like this:

function myFunc(doAwait) {
    try {
        doSomething();
        if (doAwait) {
            return Promise.resolve(doSomethingAsync()).then(doSomethingElse);
        }

        return Promise.resolve(doSomethingElse());
    } catch(e) {
        return Promise.reject(e);
    }
}
Related Topic