Live data from Hacker News

V8 adds support for top-level await

chromium.googlesource.com

301–310 of 310 posts

Re: V8 adds support for top-level await

#301
post #296

Earlier quoted context omitted.

Time deciding if you can/should rebind a variable or not is a waste of developer time.

I sort of agree; I solve this by never using let and never rebinding :) No need to think about it at all.

Then you end up playing this game of jumping through hoops to omit variables. It's a tempting waste of time because it feels productive.

Re: V8 adds support for top-level await

#302

Earlier quoted context omitted.

By waste of time do you mean performance or coding time? I feel like writing a character more is not a waste of time, if you are just following the convention that anything that is not going to be muted should be signed explicitly. It's not to prevent bugs, but for readability and ease of use.

Time deciding if you can/should rebind a variable or not is a waste of developer time.

You will know ahead of time whether you're going to be rebinding a variable. The use of const is a hint to the next person reading your code, since they won't be privy to your thought process.

In an ideal world, const would be the default, and you would have to opt into non-const.

Re: V8 adds support for top-level await

#303

Earlier quoted context omitted.

Here's an example of how you might get a race condition in JS: async function deduct(amt) { var balance = await getBalance(); if (balance >= amt) return await setBalance(balance - amt); } One way to resolve this would be with a mutex to protect the balance during the critical section (which is async). What would you suggest instead?

More subtly, here's an example of a hidden race condition in JS: async function totalSize(fol) { const files = await fol.getFiles(); let totalSize = 0; await Promise.all(files.map(async file => { totalSize += await file.getSize(); })); // totalSize is now way too small return totalSize; }

This is an interesting example because it demonstrates a way to confuse programmers that wasn't previously possible. Thanks for sharing it; it was a gem on an article otherwise full of confused comments.

After sharing it at work, someone pointed out that it isn't technically a race condition. The problem isn't caused by operations happening in an unpredictable order. It's unlikely that any of the promises are already resolved, so the lhs is always evaluated first. It's just that the programmer is surprised by the order of operations.

The takeaway is unsurprising: that `await` should be a signal to make one think carefully about state change; having `await` right after `+=` should be a big signal.

But the fact that an unwary programmer can actually be tripped up is interesting, despite some other comments on this article claiming such trip-ups are inevitable.

Re: V8 adds support for top-level await

#304
post #237

Earlier quoted context omitted.

The function is both synchronous and asynchronous until it is called by the caller. This is called Shannon's Cat. Jokes aside, I'd like to add that just because a function returns a promise doesn't mean the caller will always want to wait for it to resolve. I think of `await` as a simple modifier that casts the return value from a `Promise ` into `T`. By getting rid of the modifier, we can no longer assume that the c…

You're right of course, and I have zero data to back this up other than anecdotes from my own experience, but still I posit the most common case is that the caller wants to await the return value, not run the function asynchronously. This is why I think it'd make more sense to flip the semantics so you'd have implicit await, and have to explicitly mark the things you want to run asynchronously.

Implicit await would be a nightmare. You could never tell looking at a given block of code whether it yields to the event loop or not, introducing invisible concurrency problems. Even static types wouldn't solve this without looking at every value and function return type.

Re: V8 adds support for top-level await

#305
post #228

Earlier quoted context omitted.

But try/catch makes swallowing errors explicit, you have to catch it to swallow it. With promises it's the opposite situation, errors will be swallowed unless you explicitly handle the rejection. At least the runtimes have grown up to show console output when there's an unhandled rejection, but man it was pretty dark for a while. > Does the `x = foo()` block/implicitly await? Yes, that's what I'd expect, because `foo…

> With promises it's the opposite situation, errors will be swallowed unless you explicitly handle the rejection. Yes, I've been bitten by this too, it's certainly a drawback with the design of Promises. I wouldn't describe it as magic though, since both the implementation and the impetus are easy to understand. > Actually, it doesn't even have to be `readFile` that changes, it might be a function that it depends on,…

> I wouldn't describe it as magic though, since both the implementation and the impetus are easy to understand.

That's fair, magic may have been a bit hyperbolic.

> [...] just like if readFile() were changed from returning a string to returning a File object

But that would change the semantics of the function, it literally changes the return type. My point is that adding `async` really just changes the meachanics of the function, not the semantics. If my function returned a string before, and I add `async`, it'll still return a string; just eventually. As a caller, I don't really care, I just want the darn string.

ometimes, as a caller, I do care, and that's exactly why I think have the caller decide when to run something async makes more sense. (There's a whole other discussion that could be had here about how JS promises are a poor async abstraction anyhow, but I digress.)

> But this isn't a subtle bug, it completely breaks as soon as readFile() is changed from sync to async, right?

No it's definitely subtle. In the example I gave, the code would use the default empty array value when there's an error reading the file, for whatever reason. For the happy path, it'll work just fine, though it probably wouldn't deal with invalid input very well. Change the mechanics of readFile to async though and it'll always return the default value, even though the semantics of readFile stays the same. It still returns a string, just eventually, but because the code expects a string, it'll always break because it gets a promise instead. Add `await` and it'll be fine, but now whatever function that code is in is async, and whatever function calls that needs to also `await`, ad nauseam.

> You don't seem like a bad programmer, which is why I'm skeptical of the example you gave.

Hey, thanks! :o)

To your point though, it's definitely representative of the kind of code I come across on a regular basis. Many a times have I had to help colleagues debug this kind of issue, and many a times have I shot myself in the foot in similar ways. In any case, JS async/await semantics are set in stone now, and it's probably too dynamic a language for something like implicit await to work (performantly) anyhow, as previously mentioned.

I appreciate you taking the time to discuss, it's nice being challenged on the actual topic, without it devolving into ad hominem nonsense. There are still good corners of the internet after all!

Re: V8 adds support for top-level await

#306
post #236

Earlier quoted context omitted.

But it can change under your feet – someone might change a function to be async, that used to be sync, and now your code is broken. The code does the same thing, it's just that it turned from returning a value to returning the promise of a value, and now your code is broken. Maybe it's not the function you're calling, but a function further down the stack, that you don't even know about. It may be that the docs are b…

> But it can change under your feet – someone might change a function to be async, that used to be sync, and now your code is broken. Someone might change a function that returns a single value to return an array, and now your code is broken. Someone might rename the function, and now your code is broken. This is the nature of breaking changes, and the same solutions apply.

Yeah but that changes the semantics of the function, whereas `async` arguably just changes the mechanics. The promise itself is not interesting, it's whatever value it (eventually) returns. My point is that a language that had implicit await would let you go on making function as async as you want them to be, and callers would be none the wiser. It'd also allow the caller to decide when to run things asynchronously and even truly defer values, something which JS promises can't do since they immediately execute, but that's an altogether different discussion.

Re: V8 adds support for top-level await

#307
post #237

Earlier quoted context omitted.

You're right of course, and I have zero data to back this up other than anecdotes from my own experience, but still I posit the most common case is that the caller wants to await the return value, not run the function asynchronously. This is why I think it'd make more sense to flip the semantics so you'd have implicit await, and have to explicitly mark the things you want to run asynchronously.

Implicit await would be a nightmare. You could never tell looking at a given block of code whether it yields to the event loop or not, introducing invisible concurrency problems. Even static types wouldn't solve this without looking at every value and function return type.

Would love to learn what concurrency issues you'd see with implicit await, that you presumably wouldn't see otherwise. You're probably right, I just can't think of any examples.

Re: V8 adds support for top-level await

#308
One reason why this is actually big is it reduces the boilerplate needed to write shell scripts in Node.

I think seemingly tiny moves like this can reduce a certain cognitive overhead/feeling of unfamiliarity associated with learning a programming language. Essentially, I am hoping that this will help bring new talent to the desktop OS space, effectively allowing Web devs to "break free" from browsers/Electron/REST server.

Maybe it's just me, but I find that ES somehow manages to be useful over a wide spectrum of problem complexities, i.e. it seems that a JavaScript program may grow more gracefully than one written in Bash. (Though I've gained new appreciation of Bash since I first stated this on HN and got downvoted to hell for failing to speak in common idioms.)

Re: V8 adds support for top-level await

#309
post #275

Here's a counter-argument: https://gist.github.com/Rich-Harris/0b6f317657f5167663b493c7...

Was any of these concerns allayed?

Just stick to a sane functional style and you should be OK. I would mostly consider stateful modules an antipattern in any long-running piece of software such as a Web app (server or client). Normally you'd like to use some sort of explicit state store (Redux, database, etc) in an app like that.

Stateful modules (whether sync or async) make testing harder - suddenly you're exposed to the "wonderful" world of dep injection, monkey patching and mock libraries. Isolating different features of your program for testing should be as easy as passing a different set of arguments to the entry point of that code path.

On the other hand, when working on some sort of "run-once" script, it's perfectly fine to use modules as a unit of encapsulation of state.

That's where async imports can really shine - suddenly you don't need to alienate readers of your program with callback hell, .then() chains or IIFEs, which are in effect just a bunch of redundant punctuation that gives JavaScript a bad name.

Re: V8 adds support for top-level await

#310
post #296

Earlier quoted context omitted.

I sort of agree; I solve this by never using let and never rebinding :) No need to think about it at all.

Then you end up playing this game of jumping through hoops to omit variables. It's a tempting waste of time because it feels productive.

Strangely it turns out that rebinding variables is a really uncommon need, so there's pretty much zero game playing.
Post reply on HN