Earlier quoted context omitted.
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.
The main benefit of let/const over var is that it's block scoped. The benefit of const over let is pretty much nothing, much. It only prevents some limited form of re-binding. You can still easily re-bind const variables from inside a function: const x = 1; (function() { const x = 2; console.log(x); })() or from an argument: const x = 1; (function(x) { console.log(x); })(2) So it has limited value in any code that us…
V8 adds support for top-level await
281–290 of 310 posts
Re: V8 adds support for top-level await
#282Earlier quoted context omitted.
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.
I'm with you. Though typing `if (a = 1) {}` happens to me sometimes, and const may catch this earlier. I don't use a linter anymore, but I suppose any serious linter would warn about assignement in a condition, anyway.
The popular airbnb eslint rules[1] require the use of const where a variable is not reassigned, which I've occasionally found handy.
[1] https://github.com/airbnb/javascript#references--prefer-cons...
Re: V8 adds support for top-level await
#283So COMEFROM is now a first-class feature of the most popular programming language in the world. Intercal really was ahead of its time.
I'm not sure I quite see the analogy to COMEFROM. The "problem" with COMEFROM is that at the "target" location (the one control comes from) there is no in-source indication of the control flow transfer. So what looks like linear code turns out to have this unexpected detour to the location of the COMEFROM instruction. This hinders understandability of the code. "await" in JS doesn't have that problem: there is an exp…
That's the main issue. The overall control flow cannot be known until the entire abstract syntax tree is generated.
Re: V8 adds support for top-level await
#284Earlier quoted context omitted.
I like your idea, but I don't see how it could work in an untyped language. Consider: function foo() { return 1; } function bar() { return fetch('http://example.com'); } // implicitly async function qux() { const fn = Math.random() > 1/2 ? foo : bar; fn(); return 1; } Is qux() synchronous?
The point isn't so much whether qux() is async or not, it's whether the caller wants it to execute before subsequent statements or not. In the current state of the world: const a = await qux() const b = qux() const c = await qux() const d = (await b) + 5 But if I had my little way: const a = qux() const b = async qux() const c = qux() const d = b + 5 The weird one is `d` of course, why would it implicitly await there…
What I'm asking you is, how does anyone, be it the programmer, compiler, or runtime, know whether to block on qux() or not, given that it sometimes synchronously returns 1?
Are you saying that in your proposal, it would become part of the calling convention that any time any function at all returns (and no 'async' keyword was used), the callee would check if a Promise was returned and if so, return a continuation promise?
That is no small runtime cost.
In an untyped language like JS, the cases where static analysis could determine whether a function returns a Promise or not are vanishingly few, probably about the same as the cases where a function can be inlined. Remember, anyone at any point can overwrite Array.prototype.push to be anything they want, including a function that returns a Promise. Any function that takes and calls a callback might be calling an async function. Any math or string operation could be calling .valueOf() or .toString(), which might be async.
Re: V8 adds support for top-level await
#285Earlier quoted context omitted.
> and the only way to know if you need await is to peruse docs (hoping that they're accurate) or judiciously sprinkle it everywhere. Knowing whether what you’re calling is async is part of knowing what you’re calling at all. Sprinkling await everywhere to try to mask the difference is horrifying. (I kind of wish it didn’t work on non-thenables for that reason – half the time, it’s a bug.)
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…
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.
Re: V8 adds support for top-level await
#286Earlier quoted context omitted.
Javascript devs, for all their flaws, understand async programming far, far better than the average C programmer. Indeed, your assertion that we need "locking primitives" to counteract "race conditions" is evidence of that. Yes, JavaScript can have race conditions, but not multi-threaded race conditions that cause resource contention [0]. So what good would locking primitives be? And as a solution to single-threaded…
> (also ignorant, because 1990s C was decidedly synchronous) unless you were programming in... any GUI toolkit ever except the most toy ones ? even win 3.1 GUI primitives were async
I was thinking about C network programming, which despite what people are saying on here, was not event driven in the 1990s (I was there).
Re: V8 adds support for top-level await
#287Earlier quoted context omitted.
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 yiel…
This conversation was talking about access to variables and data within Javascript code itself. Any language is open to data races when dealing with external systems. I can see why having a `lock` construct can be helpful here, but it seems extraneous when the actual language doesn't support concurrent access and simple packages already exist. The 'async-lock' is just a wrapper around a few variables, and only works precisely because JS is already single-threaded and serialized.
Re: V8 adds support for top-level await
#288Earlier quoted context omitted.
How is swallowing errors magic? try/catch does that and predates ES3. To clarify your example, what about: function foo() { const val = async (1 + 2) return val; } const x = foo(); Does the `x = foo()` block/implicitly await? > if you forget an await you've probably introduced a bug, and the only way to know is ... docs Given that async is "contagious", I'm having a lot of trouble imagining a scenario where a codepat…
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…
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, causing bugs further up the call stack.
I don't think it's possible for readFile to become async without at least some change to it (possibly just adding 'async' and 'await' keywords, but at least some change), except maybe a rare case of a tail call.
> even though it seems everything should be fine
In what way would it seem that everything should be fine? If readFile() were changed from sync to async, wouldn't every single call to readFile() in the entire codebase need to be changed, just like if readFile() were changed from returning a string to returning a File object? It's not like most or even any at all of the calls to readFile() wouldn't need changing, then I could see how it might seem like everything would be fine.
> breaks in a subtle way
But this isn't a subtle bug, it completely breaks as soon as readFile() is changed from sync to async, right? No testing, automated or manual, of this codepath would work at all after the change, right? It's not like a cursory smoke test of this codepath seems to work fine, then I could see how the bug could seem subtle.
> I still keep running into dumb situations like the above. I still keep running into dumb situations like the above
You don't seem like a bad programmer, which is why I'm skeptical of the example you gave.
Re: V8 adds support for top-level await
#289Earlier quoted context omitted.
Javascript devs, for all their flaws, understand async programming far, far better than the average C programmer. Indeed, your assertion that we need "locking primitives" to counteract "race conditions" is evidence of that. Yes, JavaScript can have race conditions, but not multi-threaded race conditions that cause resource contention [0]. So what good would locking primitives be? And as a solution to single-threaded…
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?
You can just use a busy flag. I am not familiar with JS, so this is approximate syntax.
while (busy) { await busyIsFalse } busy = true
Critical Section
busy = false
notify busyIsFalse
Simple boolean flags will work
Re: V8 adds support for top-level await
#290Earlier quoted context omitted.
> and the only way to know if you need await is to peruse docs (hoping that they're accurate) or judiciously sprinkle it everywhere. Knowing whether what you’re calling is async is part of knowing what you’re calling at all. Sprinkling await everywhere to try to mask the difference is horrifying. (I kind of wish it didn’t work on non-thenables for that reason – half the time, it’s a bug.)
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 async/await makes this better, because a function marked async always returns a promise.