Live data from Hacker News

Top-level await in JavaScript is a footgun

gist.github.com

21–30 of 115 posts

Re: Top-level await in JavaScript is a footgun

#21
post #10

Am I the only one who is happy using normal callbacks? I think they are the best representation of the asynchronous flow.

No you're not. I'm fine with w/ever abstraction, but prefer callbacks and their composition (`async`, events, streams…) over others for simplicity and their behavior matching expectations.

Re: Top-level await in JavaScript is a footgun

#22
I'm not terribly familiar with this new proposal but I have used the regular async/await features quite extensively and can't really see a problem here.

Since async/await deal with promises, there's nothing stopping anyone from not awaiting a dependency at the top level so that some loading logic can be run.

In addition, since these are promises, there's nothing stopping us from awaiting multiple promises at once in parallel like so:

    const [dependency1, dependency2] = await Promise.all([promise1, promise2]);
All await does is schedule the resumption of the code following an await later on, so any JS not depending on this blocking dependency can continue to run. That is, await doesn't block the entire execution, unless the rest of the entire app code is sitting behind an await.

I don't even understand why top level await is necessary given HTTP 2 server push. The point is that import statements at the top can be statically analyzed so the web server can determine which dependencies to push down to you with your request. That's not quite here yet, but by the time this proposal is ready I'm sure it will be.

I guess if you need to use runtime evaluation for something to determine you're dependencies it makes sense but I've found that's rarely the case.

Re: Top-level await in JavaScript is a footgun

#23
post #11

Earlier quoted context omitted.

Well, I was happy using normal callbacks, but then promises made me a bit happier and now I even happier with async/await. You can definitely write clean code with only callbacks, but one has to be pretty careful if there are many nested asynchronous actions. Promises and await make that code very much clearer.

Also, if you're trying to do something after multiple async operations, you've got to manually count your callbacks. (As opposed to using Promise.all)

No. You use flow management library. Just how you don't manually execute multiple promises with `Array.forEach` and same manual counting. Latter just happens to be in stdlib while former is userland.

Re: Top-level await in JavaScript is a footgun

#24
I was never a fan of async/await in C#, I just never found it that useful.

I've seen examples of it in JavaScript and the author is always like, "Look at what you normally have to write and now look at what you COULD write with async and await!"

And it's like the same goddamn code with a few minor differences.

If they axed the whole proposal, I could get through this holiday season without even being depressed a little bit.

Re: Top-level await in JavaScript is a footgun

#25
post #8
post #2

> Even assuming all goes well, you've prevented yourself from doing any other work, like rendering views that don't depend on that data. Is that right? `await` is non-blocking, no?

`await` allows the event loop/job queue to run while waiting. However, while using `import` declarations , your module will not run until all imports have completed; this means that your module will be suspended while the dependency awaits. If your app is shipped as a single bundle this means your entry point would be unable to run anything while dependencies are awaiting if you use `import` declarations. If your app…

Exactly correct. But note that

> your entry point would be unable to run anything while dependencies are awaiting

is very different from the situation with synchronous I/O (in a single-threaded environment).

With sync I/O, not only is your entry point unable to do anything (which is what it chose to do, by using `import` instead of `import()`), your entire app is unable to do anything! So other entry points are also blocked.

Even worse, since sync I/O blocks the event loop, it prevents the user from interacting with your web page or Node app---e.g. scrolling, clicking links, pressing Ctrl+C to exit, and so on.

Re: Top-level await in JavaScript is a footgun

#26

Earlier quoted context omitted.

Also, if you're trying to do something after multiple async operations, you've got to manually count your callbacks. (As opposed to using Promise.all)

No. You use flow management library. Just how you don't manually execute multiple promises with `Array.forEach` and same manual counting. Latter just happens to be in stdlib while former is userland.

Please give an example of a flow mgmt lib.

Re: Top-level await in JavaScript is a footgun

#27
post #10

Am I the only one who is happy using normal callbacks? I think they are the best representation of the asynchronous flow.

I think "async functions" are peak async handling. That is either a function returns synchronously, or returns a promise. Anything more feels like fiddling.

Re: Top-level await in JavaScript is a footgun

#28

This is basically the same old argument against `await` itself: that it allows developers to write bad code that should be parallelized more (by using Promise.all etc.). It didn't stop await inside async functions, and it's not going to stop top-level await. (The argument also seems to be predicated on some fundamental misunderstandings, in that it thinks everything would have to be sequentialized. See my other repli…

Thanks for clarifying the point re module evaluation not being sequential – that would seem to break some fundamental guarantees about execution order, but I guess that's a separate discussion. The point stands that your entry point has to wait until each of its dependencies and each of their dependencies (&c) have finished before your app can start, and it unavoidably slows down module loading.

> This is basically the same old argument against `await` itself: that it allows developers to write bad code

It magnifies the effect to a degree that isn't immediately obvious – hence footgun. Users are the ones who will suffer, therefore it's right that we exercise some restraint.

Re: Top-level await in JavaScript is a footgun

#29

Earlier quoted context omitted.

No. You use flow management library. Just how you don't manually execute multiple promises with `Array.forEach` and same manual counting. Latter just happens to be in stdlib while former is userland.

Please give an example of a flow mgmt lib.

Probably the most popular one is `async` — http://caolan.github.io/async/.

Re: Top-level await in JavaScript is a footgun

#30
post #22

I'm not terribly familiar with this new proposal but I have used the regular async/await features quite extensively and can't really see a problem here. Since async/await deal with promises, there's nothing stopping anyone from not awaiting a dependency at the top level so that some loading logic can be run. In addition, since these are promises, there's nothing stopping us from awaiting multiple promises at once in…

Agree that `await` by itself is useful, and your example shows the correct way to use it for concurrent activity. The problem with top-level await is that any modules depending on a module with a TLA cannot execute until it's done – the effects cascade and magnify throughout your app, rather than being confined to an explicitly async function.
Post reply on HN