Live data from Hacker News

JavaScript async/await implemented in V8

chromium.googlesource.com

201–210 of 227 posts

Re: JavaScript async/await implemented in V8

#201

Earlier quoted context omitted.

Is the syntax composable? Can I do const json = await (await fetch(https://api.github.com/orgs/facebook')).json(); or do I have to name it?

What you asked for is whether `await` is idempotent. No it isn't. The "argument" to `await` is a Promise, and the "return value" of it is the resolved value of the Promise (i.e. `Promise#then`). EDIT: I missed the `.json()` part, but I suppose it doesn't return a Promise, no?

This is totally not what I'm asking, thanks.

Re: JavaScript async/await implemented in V8

#202

Earlier quoted context omitted.

Allow me to make both a theoretical and practical argument. It's been said that "callbacks are imperative; promises are functional". It's true. Furthermore, callbacks structure control flow and promises structure data flow. Instruction scheduling is an explicit sequence with callbacks (well, assuming the API calls you back precisely once), but scheduling is an implicit topological sort of the directed acyclic depende…

This is not quite true with regards to promises - one can do getY(x) .then(returnedY => Promise.all([Promise.resolve(y), zPromise()]) .then([y, z] => { ...another side effect...; return Promise.all([Promise.resolve(y), Promise.resolve(z), sideEffectPromise()]) .then([y, z, _] => f(y, z)); Not the cleanest, but you preserve the isolation without relying on polluted variables bleeding into function scope. In addition,…

1) Yes, you can restructure/destructure variables at each step, but you're just unifying the control flow and data flow by hand. Yet another flavor of human compiler.

2) catch's entire purpose is to be a catch-all for unexpected errors. For expected errors, it's better to have explicit error values. Bluebird.js at least lets you differentiate .catch from .error, where .error handles the explicit error values generated from traditional Node.js callbacks.

Re: JavaScript async/await implemented in V8

#203
post #124

Earlier quoted context omitted.

This right here. One of my friends (a more experienced developer) told me at coffee one day, "I use const for everything" which really stuck with me. It really helps make it clear if you need a mutation to have let stand out.

I just wish let was in fact const (and something like "local" could be let), simply because the keyword let is nicer to type, easier to read, and more importantly better in line with the meaning of let in Lisp/Scheme/ML/OCaml/et al.

Yeah, I was thinking the same! I was even considering writing a custom babel transform to do this for me :P

Re: JavaScript async/await implemented in V8

#204

Earlier quoted context omitted.

"Pyramids" are not that useful for complex flows, just as synchronous-looking code, but for something as simple as your example they are equivalent in complexity, maybe even less complex, because they don't have additional implicit behavior introduced by async/await. Still, worlds better, than CSP with channels.

async/await ends up being the less complex thing, my "simple" example is an extreme that sometimes but rarely happens. When was the last time you saw that in synchronous code? It happens, certainly but the synchronous default is to only handle what you can handle and then pass everything else back up the chain. The asynchronous default with async/await is the same, and you can rely on default error propagation in the…

First of all, exceptions are not a great way to handle errors, because they are implicit. There is no special keyword, like "await", to permit a function to throw exception, you have to guess an implicit behavior of each function. And you will have functions that never throw exceptions, functions that do, functions that lie about whether they do or do not. You will have to remember that at all times and be very careful to always use try/catch if unsure and so on. It's a big cognitive load to have. Most of the times the easiest and the only reasonable way to deal with errors is to be explicit about them.

So, the equivalent to that code with callbacks is the one from your previous example and not the simplified one that doesn't handle errors. Not forgetting "if (error)" in this case will be exactly the same, as not forgetting "catch (error)" or "if (error)" if you handle errors properly in the first place. But these are just patterns and with enough consistency they don't introduce much cognitive load. What does is implicit behavior and you don't have one with callbacks in your example, but you do with await. It's not as bad, as with threads, but still a little bit worse, than with callbacks.

Re: JavaScript async/await implemented in V8

#205

Earlier quoted context omitted.

async/await ends up being the less complex thing, my "simple" example is an extreme that sometimes but rarely happens. When was the last time you saw that in synchronous code? It happens, certainly but the synchronous default is to only handle what you can handle and then pass everything else back up the chain. The asynchronous default with async/await is the same, and you can rely on default error propagation in the…

First of all, exceptions are not a great way to handle errors, because they are implicit. There is no special keyword, like "await", to permit a function to throw exception, you have to guess an implicit behavior of each function. And you will have functions that never throw exceptions, functions that do, functions that lie about whether they do or do not. You will have to remember that at all times and be very caref…

I'm sorry you don't like exceptions. It's a pattern that's pretty well understood at this point, has been in the JS language for quite some time now and other languages for even longer.

«So, the equivalent to that code with callbacks is the one from your previous example and not the simplified one that doesn't handle errors.»

No, it isn't. It really isn't. The callback version isn't doing any sort of handling of errors, it's just laddering them, passing them back up the chain. The async/await version is doing the same automatically, wiring together for you the error handling to pass errors back to calling functions.

Even if you did want to handle every possible error/exception that could be thrown in doTheThing(), you don't really have to go all the way to the "parade" version, as only one try/catch should be sufficient in doTheThing().

The issue here is that where you see error handling as a cognitive load, the general best practices for error handling have mostly leaned to the goal that exceptions are for actual exceptional cases and catching exceptions should be left to cases where the user can actually fix the exceptional situation (rare) or logged somewhere appropriate in a global handler.

If you are unsure if you should handle an exception, don't handle the exception. Let the calling function catch, or let it continue bubbling up to whatever global exception handlers you want to set, or even just leave them for the browser's Unhandled Exception Handler and Unhandled Rejected Promise Handler to spit out debug information in its dev tools console. Don't bother remembering anything, just let your tools do their job.

The difference between catch (error) and if (error) in the callback example is that if you "forget" catch (error), it bubbles up to your browser's handlers, but if you forget if (error) it doesn't stop execution, it doesn't bubble up to your global toolkits and exception handlers and it doesn't bubble up into your dev tools debuggers.

(One thing I realized in writing this: due to my rustiness in callback coding I forgot that they should be if (error) return callback(error, null) to properly stop execution, which you want in the default case of not handling the error but passing it back up the chain. Small mistake that could cause debugging headache and adds to my point that the little things that are easy to forget that you always must do in the callback world can have a major impact on debugging...)

Re: JavaScript async/await implemented in V8

#206

Earlier quoted context omitted.

> although technically you can change the data, just not the reference This is why I'm hoping to see native JS immutable data structures eventually (maybe it's already in a proposal somewhere?). ImmutableJS and Mori are great, but having a native solution that's available everywhere would be ideal.

Consider looking at other languages. ClojureScript does a pretty good job at immutability, Elm is great for immutability + strong typing, and PureScript adds in Haskell's advanced type system (typeclasses, HKTs, etc.)

Definitely. ClojureScript is what I usually choose for my own projects, but the reality of the front-end job market is that JavaScript still dominates, so improvements to JavaScript itself will still have a significant impact on the lives of developers everywhere regardless of the existence of other compile-to-JS languages.

Re: JavaScript async/await implemented in V8

#207

Earlier quoted context omitted.

Fetch does have streaming uploads and downloads, and a quite some other features which doesn't come with xmlHttpRequest. Making it not strictly inferior to XMLHttpRequest

Will have. Future tense. Not present tense.

Present tense: https://domenic.github.io/streams-demo/

Re: JavaScript async/await implemented in V8

#208
post #16

Earlier quoted context omitted.

> (e.g. multiple concurrent calls via Q.all, multiple "returns" via callback arguments) How about: async function main () { try { const responses = await Promise.all([ fetch('https://api.github.com/orgs/facebook'), fetch('https://api.github.com/orgs/facebook') ]); const jsons = await Promise.all(responses.map(res => res.json())) } catch (err) { console.log(err) } } I think this is pretty clear and not needing any lib…

I will admit that I hadn't realized async worked on Promises. This is definitely a very clean solution, though not one that can be seemingly achieved without Promise.all. There is, of course, no library needed to use pure promises for the same functionality, though. My point is that all of this is possible without async/await, which to me are abstractions that cloud the landscape, obscuring the real evented nature of…

I'd say a bad programmer can produce shit regardless of the tools he is given. What async/await does is make complex async code much easier to read and maintain. Of course, you have all the expressive power of callbacks and promises at your disposal too. That's one of the great things about it. It's implemented on top of these constructs and they remain accessible.

Re: JavaScript async/await implemented in V8

#209
post #4

The moment I started using async await (with babel) combined with the new fetch API so many libraries got obsolete. Getting data is as easy as: async function main () { try { const res = await fetch('https://api.github.com/orgs/facebook'); const json = await res.json(); console.log(json); } catch (e) { // handle error } } So I am quite happy when this lands in modern browsers asap.

[deleted]

Re: JavaScript async/await implemented in V8

#210

Earlier quoted context omitted.

"Pyramids" are not that useful for complex flows, just as synchronous-looking code, but for something as simple as your example they are equivalent in complexity, maybe even less complex, because they don't have additional implicit behavior introduced by async/await. Still, worlds better, than CSP with channels.

async/await ends up being the less complex thing, my "simple" example is an extreme that sometimes but rarely happens. When was the last time you saw that in synchronous code? It happens, certainly but the synchronous default is to only handle what you can handle and then pass everything else back up the chain. The asynchronous default with async/await is the same, and you can rely on default error propagation in the…

Don't forget that for every await - you or preferably someone else has to write the Promise boilerplate!
Post reply on HN