Comment by derangedHorse

4 years ago

Asynchronous code can sometimes be difficult to write efficiently so having implicit awaits might help with avoiding accidentally made fire and forget calls. An interesting concept might be to explicitly call a function as asynchronous with a new keyword flipping the typical usage of ‘await’. I’d still advocate for the usage of ‘async’ in function signatures though as it helps when reasoning through an asynchronous code base.

I think it would be awesome for Typescript to introduce sync functions. So think of that as completely flipping the dialog on async/await to await by default:

    sync function x() {
        const taco = getTaco() // getTaco returns Promise<Taco>, but taco automatically resolves it in a sync function
        // Similarly, you can tell it to not wait
        const ptaco = nowait getTaco();
        // ptaco is a Promise<Taco>
        const taco2 = ptaco; // taco2 is a Taco because the ptaco symbol is treated like (await ptaco) without nowait
        // Also, since ptaco has already "awaited", future
        // access would be 0 delay as it's basically a resolved promise.
    }

Of course, similar to an async function, sync functions would also return a promise.

Probably a dumb idea but I would use it personally.

I started working in node around version 0.8, before both native Promises and async/await.

I worked with guys that started after async/await.

The new guys just think of everything like it's synchronous. They don't understand Promises. They never look at code and think "I can run this in parallel with Promise.all and a reducer". They just await each thing one at a time.

So, I'm not sure the async/await annotations are really helping us when devs just use them like decorations that just have to be there for it to work.

  • I'm new to NodeJS but it was my understanding that using await like that would help by not blocking the thread, leaving node free to process other requests.

    • await won't block Node from handling other requests but it will block the thread that is awaiting. For example, these will execute one after the other (the "bad way"):

        await slowThingOne();
        await slowThingTwo();
      

      but these execute in parallel, awaiting until both are finished (the "good way"):

        await Promise.all([slowThingOne(), slowThingTwo()]);

      1 reply →

  • Don't forget to put each await in a try/catch. You are handling all errors aren't you!? ;)

But then how do you gather promises together to run them in parallel? For sophisticated apps this is crucial.

This is exactly how I remember it working in the language I mention (which, by the way, is called hyperscript[1].) The semantics where flipped such that you'd explicitly mark calls or functions as async, rather than await, if you wanted them to run asynchronously.

I run into subtle bugs all the time due to missing awaits, it's incredibly frustrating.

[1]: https://hyperscript.org/posts/2021-04-06-aysnc-transparency-...

  • > I run into subtle bugs all the time due to missing awaits, it's incredibly frustrating.

    If you use TS, ESLint's `no-floating-promises` rule (or the equivalent in other linters) is _such_ a requirement