Live data from Hacker News

V8 adds support for top-level await

chromium.googlesource.com

191–200 of 310 posts

Re: V8 adds support for top-level await

#191

Earlier quoted context omitted.

Yes but async/await is for concurrency, not parallelism. Only one or the other "coroutine" will run at any time so what is the lock protecting? There's no way for multiple branches of code to access the same variable at the same time in JS. What else would a reader/writer lock be used for?

Locks are for concurrency. Parallelism is orthogonal. When you are forced to yield inside of your critical section (a database call, a file write, whatever), as is common in NodeJS, you must acquire a lock that another coroutine can't run through.

He got the terms wrong but he’s absolutely right.

> There's no way for multiple branches of code to access the same variable at the same time in JS.

This is 100% true and it’s the very reason why we do not need locks. There is no thing called a critical section in JavaScript because in JavaScript all of your code runs on a single thread and it’s all equal therefore none of it is more volatile than any other piece code. All that you need to manage asynchronous concurrency is good state management, not “locks”, because there is nothing to lock since there are not multiple threads asking any of your JS code for control of execution at the same exact time. It’s all scheduled for you onto your single thread.

With that, what you don’t get in JS of course, is shared-state parallelism.

Re: V8 adds support for top-level await

#192
post #182

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?

Can anyone explain this to me, how is it a race condition?

Two concurrent calls to that code. Both of them get the same balance (100), pass the test and deduct the amount (75), getting to a -50 balance.

Re: V8 adds support for top-level await

#193
post #103
post #81

Earlier quoted context omitted.

> when you use async/await instead of promises or callbacks, things do change because two sequential lines of code are no longer two truly sequential instructions I thought async/await was just syntactic sugar for promises?

No it's not. async/await's semantic is similar to coroutines, and is implemented by them.

It is true that async functions work similarly to the coroutines found in other languages, and that some transpilers convert async functions into Javascript generator functions under the hood. However, these are both implementation details.

On the flip side, there is a Javascript transpiler called nodent which directly converts async functions into the corresponding `Promise.then` calls, with no generators in sight. This transpiler actually generates smaller & faster output than the standard generator-based approaches, since the async/await semantics map more directly to promises.

In other words, async functions really are semantic sugar for promises, even if they have some similarities to coroutines / generators.

To try it yourself, just go to http://nodent.mailed.me.uk/ , check the "spec compliant" option, and look at the generated output.

Re: V8 adds support for top-level await

#194

Earlier quoted context omitted.

Locks are for concurrency. Parallelism is orthogonal. When you are forced to yield inside of your critical section (a database call, a file write, whatever), as is common in NodeJS, you must acquire a lock that another coroutine can't run through.

He got the terms wrong but he’s absolutely right. > There's no way for multiple branches of code to access the same variable at the same time in JS. This is 100% true and it’s the very reason why we do not need locks. There is no thing called a critical section in JavaScript because in JavaScript all of your code runs on a single thread and it’s all equal therefore none of it is more volatile than any other piece cod…

None of the concerns of concurrency go away because you don't have threads, they go away when you have no multitasking, and NodeJS is a cooperatively multitasking environment (modulo a few minor asterisks).

So of course there are still critical sections--a critical section is a set of operations that must have uninterrupted access to a resource in order to maintain a desired level of consistency. If you have to yield (that is, `await` on a Promise or wait for the invocation of a callback), which sometimes you do have to do (i.e., you have to do IO, you've got a crunchy computation running in C++ outside of the JS loop, whatever), then you need to prevent access to that resource from whatever is being picked up next by the JS runtime while the first user is waiting for that IO to finish or that computation to come back.

To that end, locks are that "good state management" to which you refer. Most of the time one can use a mutex--the `async-lock` library is common--but I've even encountered cases where resource management must occur in structured forms and it was necessary to implement a read-write lock, where multiple readers can operate in tandem but all readers must close out before a writer can take control.

The basics don't change when your multitasking is cooperative rather than preemptive--all the same stuff still applies. This is not a controversial set of assertions. I don't understand at all where you're coming from.

Re: V8 adds support for top-level await

#195
post #55

Earlier quoted context omitted.

let plus the curly bracket scoping means that the variables only exist within the curly brackets, and not the global state.

Maybe he meant why not const?

Correct. Example doesn't show modification of the variables later, better to use const.

Re: V8 adds support for top-level await

#196
post #114

Earlier quoted context omitted.

I don't think it really makes sense to essentially say "Javascript is rife with race conditions like any other language" just because yes, you still need to use transactions when using a database.

You're reading too much into the example. Your 'database' can be your frontend js state. There is nothing in the example that limits the problem to backend development.

In that case, the code would be sync and there wouldn't be a "race condition".

Re: V8 adds support for top-level await

#197

Earlier quoted context omitted.

Using the more restrictive construct until you actually need additional features (like identifier rebinding) is just engineering 101. I think the onus would be on you to prove that using a less restrictive concept is worthwhile because it saves you two keystrokes. That, in contrast, seems like the opposite of good engineering. Like using classes over structs because class is shorter to type. The more I think about yo…

I think it can be argued both ways. I've seen a large TypeScript codebase with a pre-commit hook that enforces use of const on all non-reassigned variables. With that being done everywhere, it made for easy reading - whether a variable was being reassigned or not effectively became annotated in its declaration. On the other hand, there are some good reasons not to use use const everywhere we can. Paul Sweeney lists a…

I don't think I'd call any of those reasons good; the main thrust of them is "const doesn't do everything, so don't let it do anything". If that line of reasoning is appealing, then one might as well continue using var.

Re: V8 adds support for top-level await

#198

Earlier quoted context omitted.

Maybe he meant why not const?

Const is a complete waste of time for non-primitive types. I defy anyone to show me a single bug in a popular program that could have been prevented by using const for a function local object. It can’t be done. There are bugs caused by mutatable state. There are bugs caused by reassigning globals. There has never been a bug caused by reassigning a function local variable while leaving it mutable.

> There are bugs caused by mutatable state.

> There has never been a bug caused by reassigning a function local variable while leaving it mutable.

The latter _is_ mutable state. const doesn't prevent all mutations, but it does prevent some, while let prevents none. I'll take the limited protections of const (with awareness of its limitations; many examples of let are of confused devs trying to avoid making their objects immutable).

Re: V8 adds support for top-level await

#199

All this async code without decent locking primitives is leading to a rabbit hole of race conditions... It doesn't matter that it's all single threaded if all your function calls may or may not block and run a bunch of other code in the meantime, mutating all kinds of state. I feel like JavaScript developers of the 2020's are going to relearn the same things the C programmers of the 1990's learn, just a few levels of…

Plenty of people replied to counter this misinformation, so why is it still at the top?

Re: V8 adds support for top-level await

#200

Earlier quoted context omitted.

The Great Old Ones did not have access to any lost mystical knowledge. They at least had the advantage of not being forced to design a language for a failed startup, to be easy to learn where that's defined as resembling C, and other asinine considerations people continue to take into account nowadays. These were clearly people that were figuring it out as they went along, which they would be the firt to admit I'm no…

I'll tell you why these languages like Lisp or APL or Ada aren't actually good languages. If they were really good languages, people would not only strongly advocate for them, they would give credibility to their advocacy by writing plenty of great programs in them, even on their own time, because they are very productive in these languages. They would also create best-in-class tooling to further their productivity e…

I disagree with your position that a language is good or not based on how people appreciate or use it. You're trying to tell me garbage such as PHP is one of the best languages there is, effectively.

In any case, I can still find examples of these platforms. Emacs is such a platform. For that matter, StumpWM is a platform of sorts. A nice quality of Lisp is making any program extensible with it trivially. As for Ada, governments use it for critical systems and I can't tell you the particulars of those. They use Ada because people will die if the software fails, so they're seeking quality, not quantity. You're advocating for quantity, not quality.

As for APL, you don't build platforms or such things in APL. If you don't see the beauty in APL, then that's your loss.

They don't build platforms for others to build on, they build pillars to prove a point.

First you claimed people don't build great programs in these languages, which I've shown is false, and now you're arguing that they build things, but not things someone can build on. You're conflating extensible software with quality software here.

What actually happens with these languages is that a certain breed of highly opinionated but highly unproductive programmer gets lost in them, on their quest for a level of aesthetics or elegance or correctness that nobody but themselves actually values.

That happens, less so with Ada, but why would that even be a bad thing? Is it wrong for someone to spend time working on what they view as an ideal and finished program, rather than just writing something that's already been done and requires little thought or effort on their part? It's infinitely harder, I think, to write novel programs than it is to simply implement some specification or write a copy or something else. That's what I do with my work. I don't see why you'd look down on that.

I'll let you've the last word, if you want it. I'm not interested in replying in this chain any further.

Post reply on HN