Live data from Hacker News

V8 adds support for top-level await

chromium.googlesource.com

51–60 of 310 posts

Re: V8 adds support for top-level await

#51

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…

In a single-threaded universe, what more do you need to lock the world than a boolean variable?

Nothing really, but you'll still want be sure the lock is released correctly.

Re: V8 adds support for top-level await

#52

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…

It's best to use the phrase 'async control flow' instead of 'race conditions' when you're talking about single threaded execution.

Re: V8 adds support for top-level await

#53
I think async/await probably makes more sense in a typed language, where a compiler can tell you when you're missing an await, or at least warn you about not dealing with potential side effects and error handling. For something like JavaScript, it'd make more sense to me to have the runtime always and implicitly await the result of async functions, and instead make developers explicitly say when they wish for the result to be async. For example, instead of:

    const data = await fetch()
    push(someData) // async, runs in the background
You would do:

    const data = fetch() // Runtime detects promise and awaits result
    async push(data) // the async keyword would return a promise and execute the push function asynchronously, allowing the next line to execute
In this fantasy world the "await" keyword would work anywhere and as you'd expect – awaiting the result of any promise:

    const data = fetch() // implicitly await
    await async push(data) // this would also be "synchronous" in that it suspends execution of subsequent code until `push` fulfills or rejects the promise, and so it'd have the same effect as implicit await
Point is you'd probably await that promise elsewhere, so you'd actually store away the return value of the `async` call and later on you'd `await`, or another example would be to await a block.

Promise rejections in implicit awaits would halt execution, just like a sync function throwing an error, so you wouldn't "miss" an error somewhere because runtimes swallow promise rejections. (Well, at least Node wised up eventually.)

This means there'd be no difference in function declaration between sync and async functions, it'd be determined by whether they return a promise or not which I think should be possible to statically determine by a JIT compiler in most cases, so not adding too much (if any) overhead.

Kind of a half baked thought, but point is I always felt the async/await thing was kind of backwards in JavaScript.

Re: V8 adds support for top-level await

#54
post #21

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…

Isn't every new language doomed to relearn everything in some way?

Not everyone uses languages designed by people with no place designing a language and taken from there. Not every language is PHP, JavaScript, C++, et al.

Take a look at a Lisp, APL or a derivative, or Ada for examples of languages designed by people who knew what they were doing. Lisp grew in universities under the direction of hackers and there are several standard dialects now. APL was designed by a mathematician originally as a teaching aid. Ada was designed in a contest by the US DoD after spending a long while collecting requirements and it was then fully specified before any implementation work was done.

Re: V8 adds support for top-level await

#55
post #45

Earlier quoted context omitted.

For some use cases, the difference can be a little more dramatic. fetch(allResourcesUrl).then(async response => { let allResources = await response.json(); let pageResource = await (await fetch(allResources.page1.url)).json(); // set up page with pageResource }); can be replaced with { let allResources = await (await fetch(allResourcesUrl)).json()); let pageResource = await (await fetch(allResources.page1.url)).json(…

What's with the `let` though?

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

Re: V8 adds support for top-level await

#56

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…

> 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. Can you elaborate a bit more on this? I'm unsure about how locking in a single-threaded environment would work. And how would it really differ from async/await or promises which can handle race conditions already? One area where the lack-of locki…

In javascript anywhere you see await, you've introduced an explicit scheduling point. There are cases where even in a single threaded env you want to "wait" until some other async process is complete. To use one of the old school examples:

    function transfer(amount, acct1, acct2) {
        var current_balance = await acc1.balance()
        if current_balance > amount {
            await acct1.sub(amount)
            await acct2.add(amount)
        }
    }
Now what happens if you get multiple calls to transfer? What you want is probably something like:

    function transfer(amount, acct1, acct2) {
         await acct1.Lock()
         ....
         await acct1.UnLock()
    }

Re: V8 adds support for top-level await

#57
post #53

I think async/await probably makes more sense in a typed language, where a compiler can tell you when you're missing an await, or at least warn you about not dealing with potential side effects and error handling. For something like JavaScript, it'd make more sense to me to have the runtime always and implicitly await the result of async functions, and instead make developers explicitly say when they wish for the res…

Promises are nice in JavaScript because they’re just a value with no magic. Anything can create them, not just async functions. Generic/higher-order functions and so on can get involved without needing to know the difference. A proposal to introduce magic at calls sounds really awful, sorry.

Re: V8 adds support for top-level await

#58
post #48

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…

Data races are impossible in JavaScript because it's single-threaded. Race conditions are possible in any language that can do anything asynchronous, which is basically all of them. But the general benefit you get from JS being single-threaded is the fact that any given callback is transactional. No other code will ever come in and mutate state between two regular lines of JavaScript code. Achieving this is pretty mu…

> two sequential lines of code are no longer two truly sequential instructions

How is this different from normal multithreading?

Re: V8 adds support for top-level await

#59
post #41
post #29

Earlier quoted context omitted.

JS is single-threaded right so (...I think...) deadlocks are actually impossible. Although I guess you can still get stuck if two pieces of code are waiting on each other to satisfy some condition (and trading control of the sole thread) without using explicit locking.

Yeah, nothing about JavaScript being single threaded implies any resistance to deadlock.

It's still much harder to deadlock single-threaded code than multi-threaded code because single-threading eliminates the need for most locking, which in turn eliminates most opportunities to cause deadlocks.

Re: V8 adds support for top-level await

#60
post #58
post #48

Earlier quoted context omitted.

Data races are impossible in JavaScript because it's single-threaded. Race conditions are possible in any language that can do anything asynchronous, which is basically all of them. But the general benefit you get from JS being single-threaded is the fact that any given callback is transactional. No other code will ever come in and mutate state between two regular lines of JavaScript code. Achieving this is pretty mu…

> two sequential lines of code are no longer two truly sequential instructions How is this different from normal multithreading?

Normal, which is to say preemptive, threading can pause your execution arbitrarily.

You can wedge a NodeJS interpreter by not yielding, but you also have control over when that yielding happens.

Post reply on HN