Remix.run Logo
tbrownaw 3 days ago

The `await` keyword means "turn the rest of this function into a callback for the when the Task I'm waiting on finishes, and return the resulting Task". Returning a Task only works if your function is declared to return a Task.

The `async` keyword flags functions that are allowed to be transformed like that. I assume it could have been made implicit.

You can do a blocking wait on a Task or collection of Tasks. But you don't want to do that from a place that might be called from the event loop's thread pool (such as anything called from a Task's completion callback), since it can lock up.

captaincrowbar 2 days ago | parent | next [-]

"The `await` keyword means "turn the rest of this function into a callback for the when the Task I'm waiting on finishes, and return the resulting Task"."

Oh my god thank you. I've been trying to wrap my head around the whole async/await paradigm for years, basically writing code based on a few black magic rules that I only half understand, and you finally made it all clear in once sentence. Why all those other attempts to explain async/await don't just say this I can't imagine.

quectophoton 2 days ago | parent | next [-]

> Why all those other attempts to explain async/await don't just say this I can't imagine.

On one hand, the people who write explanations are usually those who have lived through a language's history and learned things gradually, and also have context of how things were solved (or not) before a feature was introduced.

On the other hand, the people who are looking for an explanation, are usually just jumping directly to the latest version of the language, and lack a lot of that context.

Then those who do the explaining underestimate how much their explanations are relying on that prior context.

That's why I think the ideal person to explain something to you, is someone with an experience as similar as possible to your own, but also knows about the thing that you want to know about. Because this way they will use terms similar to those you would use yourself. Even if those terms are imprecise or technically incorrect, they would still help you in actually understanding, because those explanations would actually be building on top of your current knowledge, or close to it.

This is also why all monad explanations are... uh... like that.

xiphias2 2 days ago | parent | prev [-]

It's because implementing this is not that easy: there are differences between the implementation of coroutines and await that makes it tricky (especially waiting for both CPU tasks and network events).

For Python I loved this talk by David Beazley:

https://www.youtube.com/watch?v=MCs5OvhV9S4&t=2510s

He's implementing async/await from coroutines ground up by live coding on the stage

ivanjermakov 2 days ago | parent | prev [-]

> I assume it could have been made implicit

Not quite. It gets ambiguous whether to wrap return or not. Example:

    function foo(): Promise<number> {
        if (...) { return Promise.resolve(5) }
        ...
    }
but async version is:

    async function foo(): Promise<number> {
        if (...) { return 5 }
        ...
    }
Although you can bake into the language one way or another.