5

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.

dx_over_dt
  • 313
  • 3
  • 9

2 Answers2

5

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);
    }
}
jfriend00
  • 3,572
  • 27
  • 18
  • When `doAwait` is `true`, I don't return the value of `doSomethingAsync`. – dx_over_dt Dec 01 '19 at 20:47
  • @dx_over_dt - OK, I fixed that. – jfriend00 Dec 01 '19 at 20:50
  • So if there were a lot of conditional awaits, it would produce a bunch of stringed, repeated, thens? – dx_over_dt Dec 01 '19 at 20:51
  • @dx_over_dt - Conditional asynchronous operations are simply a lot easier to code with `async/await`. – jfriend00 Dec 01 '19 at 20:53
  • Right, which is why I'm wondering how the engine handles them. – dx_over_dt Dec 01 '19 at 20:54
  • 1
    Well, the engine has `await` functionality built in. It literally suspends execution of the function body until the promise resolves/rejects. It doesn't have to rewrite code into `.then()` handlers. – jfriend00 Dec 01 '19 at 20:58
  • Ah, so it doesn't first transform the code into a `Promise` and then run that. – dx_over_dt Dec 01 '19 at 21:00
  • 1
    It doesn't need to transform it into regular `.then()` code because it can directly suspend function execution. How exactly a given engine does this is implementation dependent. It's certainly cleaner if they natively support suspending function execution upon an await without rewriting the logic. – jfriend00 Dec 01 '19 at 21:08
0

An async function has to return a promise. So to start with you may consider your;

async function af(x){
        ...
        return y;
      }

rephrased as

function af(x){
  return new Promise(v => ( ...
                          , v(y)
                          )
                    );
}

However once you do this you don't really need a try and catch stage at all since Promises natively handle that.

Please check the following at the dev tools for af(true,1000), af(true,0), af(false,1000) and af(false,0);

function boom(){
  throw "Boom..!";
}

function doStgSync(b){
  b ? console.log("Did something sycnronous..!")
    : boom();
}

function doAsyncIn(n){
  return new Promise((v,x) => n ? setTimeout( v
                                            , n
                                            , `Async operation done in ${n}ms`
                                            )
                                : x("ZERO ZERO BANG BANG..!")
                    );
}

function af(b,n){
  return new Promise(v => ( doStgSync(b)
                          , v(doAsyncIn(n))
                          )
                    );
}

af(true,1000).then(console.log)
             .catch(e => console.log(`Got error: ${e}`));
Redu
  • 101
  • 1
  • I'm not sure I follow. Can you convert my example async function into a `Promise` chain? – dx_over_dt Oct 23 '21 at 17:15
  • @dx_over_dt It is basically the same code. The synchronous `doSomething` function in your code is `doStgSync(b)` function in my code. If it's argument `b` is `true` it just works or throws an error if it is `false`. Your `doSomethingAsync` function is `doAsyncIn(n)` in my code. If `n` argument is `0` then it rejects or if not takes that many ms to resolve. – Redu Oct 23 '21 at 17:25