← Back to context

Comment by mstade

4 years ago

This looks very cool, thanks for sharing!

I took a cursory look at the docs and it looks like async/await is pretty much directly analogous to how it works in JS, with the difference that you don't need to mark functions as async in order to use the await keyword. Does this mean that if you use await in any function then any other function calling it will have to be refactored to add an await keyword, just like you have to refactor any call sites in JS if you make a function async?

I remember seeing someone here on HN showcasing a language where they did the opposite, making it so that await is implicit, so calling fetch or anything async doesn't require an additional keyword, and functions don't need to be refactored just to sprinkle async/await everywhere. I'll see if I can find that language again, but it seems to me there may be some idea sharing between the two that could perhaps yield some amazing features...

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.

      2 replies →

    • 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

      4 replies →