
Async/await support in Firefox - dallamaneni
https://blog.nightly.mozilla.org/2016/11/01/async-await-support-in-firefox/
======
chinhodado
Is there an article or book where the major "ways" of doing concurrency in
different languages are explained and compared? E.g. thread process mutex
semaphore etc. in Java et al, callback promise async await in JS, goroutine
channel in Go, task async await plinq in C#, asyncio in Python, etc. It would
be nice to have a general overview of these, what their pros and cons are and
why.

~~~
jacobsenscott
Ugh. At least when everyone was doing threads you only had to learn one model.
Then everyone had to build a better mousetrap.

~~~
pcwalton
I feel as though 1:1 threading is underrated nowadays. Most of the cited
benefits of async or M:N—especially small stacks—are actually properties that
can apply equally well to plain old 1:1 threading as well. Linux thread
spawning is really fast nowadays.

~~~
chubot
Yes I agree -- threads without shared state or with thread-safe shared data
structures is a perfectly good programming paradigm (and pretty well proven
too).

One of my pet ideas is just to implement a Go-like CSP with plain pthreads.
Channels could be pipes of pointers. Channel select is just select(). No weird
M:N runtime needed. I don't want an operating system in my programming
language.

This is just stolen from Programming in Lua chapter 30 -- threads and states (
[https://www.lua.org/pil/](https://www.lua.org/pil/) , not in the 1st online
edition unfortunately)

Lua has coroutines within the interpreter, but to utilize all the cores he
suggests layering threads and multiple Lua interpreters on top.

~~~
pcwalton
> One of my pet ideas is just to implement a Go-like CSP with plain pthreads.
> Channels could be pipes of pointers. Channel select is just select(). No
> weird M:N runtime needed.

Please do it! I feel like we've forgotten the lessons of NPTL, when everyone
tried M:N and collectively came to a consensus that M:N wasn't worth it in
practice.

~~~
chubot
OK :) I actually have a reasonable project to do it on... I'm implementing a
new shell, which is making decent progress, and I've been documenting some
interesting things here:

[http://www.oilshell.org/blog/](http://www.oilshell.org/blog/)

It's very compatible with bash so I think it has a chance of being adopted.
And I would like to add structured data pipelines, which powershell has. I was
thinking of implementing it with the threads and pipes of pointers scheme (and
probably the condition variable).

I guess the shell concurrency model is more like a subset of CSP, but the more
general CSP model seems useful and fairly easily implementable. I feel like it
should be like 200 lines of code, so I should try it sooner rather than later.
Just start porting some simple Go programs to it.

( My last post about parsing expressions got buried on HN but I think it is
fairly interesting to a specialized audience:
[http://www.oilshell.org/blog/2016/11/01.html](http://www.oilshell.org/blog/2016/11/01.html)
)

~~~
ddalex
I've just spent 1h at work (silly me) reading your blog, it is illuminating! I
love your writing style, and I can't wait to see the your shell in action!
Just the full-parse-before-execution is well worth it, especially when
deploying scripts on servers.

If you open source the project, I'd love to try giving you a hand. Anyway,
good luck with the project!

~~~
chubot
Great thanks! Yes it will be open source.

I'm rounding the corner on parsing hundreds of thousands of lines of bash
scripts now... the prototype is in Python as mentioned in the first post, and
the executor isn't complete, but if you want the parse-before-execution, that
is working well.

ShellCheck does exist though. IIRC I had mixed experience with it -- it did
actually find one bug, but on the other hand it spewed hundreds of warnings
about double quoting vars, which is technically true, but not the best use of
time for most scripts I write. I'd rather just get rid of stupid quoting
rules, which is one of the #1 priorities.

(As far as writing, I find that "omit needless words" from Strunk & White goes
a long way. Words like "very" and "a little" somehow spray themselves all over
my writing; they are rarely useful and I kill them on editing passes :) )

------
notgood
Great news.

FYI Chrome will ship with async/await support[0] in the next stable version
(55, so it's already on Chrome Canary).

[0][https://bugs.chromium.org/p/v8/issues/detail?id=4483](https://bugs.chromium.org/p/v8/issues/detail?id=4483)

~~~
apaprocki
A giant shout-out to Igalia (Caitlin Potter!), who were instrumental in
getting this implemented and shipped!

[https://blogs.igalia.com/compilers/2016/05/23/awaiting-
the-f...](https://blogs.igalia.com/compilers/2016/05/23/awaiting-the-future-
of-javascript-in-v8/)

This joins generators[1][2][3] (Andy Wingo) and arrow functions[4][5] (Adrian
Perez de Castro, Andy Wingo) as examples of the community (read: not employees
of Mozilla, Google, Apple, Microsoft) directly working on the engines to ship
these features much sooner than they otherwise would be. (Surely they'd land
eventually, but acceleration and cross-engine coordination greatly improves
time-to-dev-market.)

[1]: [https://wingolog.org/archives/2013/05/08/generators-
in-v8](https://wingolog.org/archives/2013/05/08/generators-in-v8)

[2]: [https://wingolog.org/archives/2013/10/07/es6-generators-
and-...](https://wingolog.org/archives/2013/10/07/es6-generators-and-
iteration-in-spidermonkey)

[3]: [https://wingolog.org/archives/2014/11/14/generators-in-
firef...](https://wingolog.org/archives/2014/11/14/generators-in-firefox-now-
twenty-two-times-faster)

[4]: [https://groups.google.com/forum/#!topic/v8-users/5FNvOv-
kQY4](https://groups.google.com/forum/#!topic/v8-users/5FNvOv-kQY4)

[5]: [https://wingolog.org/archives/2015/06/18/arrow-functions-
com...](https://wingolog.org/archives/2015/06/18/arrow-functions-coming-to-
chrome-45)

------
awalGarg
Note that async functions _always_ return native promises. So if you like your
fast or sugary promise libraries, you can't make async functions return those
promises. You are stuck with the native promises, which, as of now, are pretty
slow in almost all engines in comparison to the heavily optimized promise
library bluebird.

I guess we should just hope that engines will optimize their own promise
implementations. This might not matter much in front-end apps, but absolutely
does for Node apps.

Other than that, I believe it is time JS gets: 1\. An actually useful
try/catch (with pattern matching on the catched errors) 2\. Standard stack
traces across all engines

Those two will really help async/await.

~~~
Zarel
[https://kpdecker.github.io/six-speed/](https://kpdecker.github.io/six-speed/)

According to this, native Promises are 2x faster than Bluebird in Chrome and
7-8x faster in Safari, and the same speed as Bluebird in Firefox and Edge. I
remember a yearish ago they were slow, but that appears to no longer be true.

~~~
apaprocki
Part of the work Igalia did in 2016 was to improve compatibility and
performance of native Promise. It's a constantly moving target. If you single
out v8, they're constantly improving the JIT, evolving the architecture, while
individual features (e.g. generators, Promise) continually get optimized on
top of those underlying engine changes. Lots of people talk about performance
in absolute terms, but what is really needed is a proper performance test
suite for individual features and a kangax style[1] browser/engine version
perf chart (edit: like the link you posted, duh!) to track it over time
similar to the more general AWFY[2]. I guess the main issue is that the test
suite needs to be more accepted by the browser teams as a de-facto standard?

[1]: [http://kangax.github.io/compat-
table/es6/](http://kangax.github.io/compat-table/es6/)

[2]: [https://arewefastyet.com/](https://arewefastyet.com/)

------
jrvidal
I am a JS programmer and I have mixed feelings about this. I am not entirely
sold on the stuff that comes _after_ async/await. In particular, I am curious
to know what folks here think about cancelable promises [1] and the try...else
block that might be introduced. Or about async iterators [2], where you can
`yield await` stuff.

[1] [https://github.com/tc39/proposal-cancelable-
promises](https://github.com/tc39/proposal-cancelable-promises)

[2] [https://github.com/tc39/proposal-async-
iteration](https://github.com/tc39/proposal-async-iteration)

~~~
k__
Is this about the cancelation tokens they also want to force on observables?

~~~
jrvidal
Well, I was asking in general about all those new features that are in
consideration: cancelation tokens, try...else, even the await.cancelToken
meta-property [1]. It feels like a lot of baked-in syntactic support for a
very specific pattern =/

[1] [https://github.com/tc39/proposal-cancelable-
promises/blob/ma...](https://github.com/tc39/proposal-cancelable-
promises/blob/master/Cancel%20Tokens.md)

------
tlrobinson
I'm really looking forward to not having to debug my code compiled to state
machines.

Is there a good way to get Babel/Webpack to emit multiple versions of your
code compiled with different features enabled, then load the right bundle?

~~~
vcarl
There's a website, polyfill.io, that does browser sniffing and sends a minimal
polyfill. The source is available under the MIT license[1], it shouldn't be a
tremendous amount of work to set up a bunch of different builds for different
features levels, with a server in front responsible for sending the correct
bundle.

[1]: [https://github.com/Financial-Times/polyfill-
service/blob/mas...](https://github.com/Financial-Times/polyfill-
service/blob/master/lib/UA.js)

~~~
apaprocki
What you just described is what I always describe as the ideal web deployment
system. Most of my dev is in C++, but I couldn't believe the inefficiency
found in sniffing everything at runtime versus using what already exists to
serve up different pre-compiled targets specifically optimized for all the
major browser versions active in the field. It seems that products like this
that span the dev workflow (compilation) / operational (sniffing server) gap
are hard to get off the ground since many devs can't touch the ops side.

------
aboodman
Biggest advance in JavaScript since ... I don't even know. XHR? Reasonable GC
performance?

~~~
greendragon
I've intentionally been keeping myself ignorant about async/await in JS until
it's common enough I can consider using it natively without any great concern
about cross browser compatibility. Why is everyone so excited for it? From the
example it looks like a thin syntactic sugar layer over normal promises,
what's so great about saving one level of indentation?

~~~
aboodman
Well, I guess there are three main reasons I'm so excited about async/await:

1\. It allows you to reason linearly about code with IO mixed in, without
blocking the entire event loop. This is incredibly useful. Computer
programmers are very good at reasoning linearly. It is just much, much more
comfortable [1] to think about code that uses async/await than the same code
with promises.

2\. I think the way that promises and async/await interop is very beautifully
designed. The way it ends up working in practice is that you can write a
function that "blocks"[2], but if you later decide you want to call it in
parallel with something else, that's fine because async functions are just a
thin wrapper around Promises. So you can just take that existing function and
call `Promise.all()` on it. Similarly if you start with a function that
returns a promise, and you decide you want to call it in a blocking way -- you
just do `await thingThatReturnsPromise()`. This is an almost perfect example
of primitives composing to be more than the sum of their parts.

3\. (and this is worth the price of admission alone) error handling works
properly and automatically. If you `await` an async function and it throws,
you'll get a plain ol' JavaScript error thrown which you catch in the normal
way. If I never debug another hung JavaScript app that dropped a rejected
promise on the floor it will be too soon.

[1] please don't tell me that I just don't "get" asynchronous programming. I
was writing js event handlers when you were in diapers (something something
lawn something).

[2] `await` doesn't really block the event loop, it just appears to.

~~~
rictic
One more thing that's particularly nice about `async/await` is just using the
`async` part. For existing functions that should always return promises, when
that function is `async` you can be sure of it. Even if it throws. Even if it
returns a value that sometimes isn't a promise.

Makes writing correct code easier.

~~~
breatheoften
I'm not up to speed on async/await -- do you happen to know if an async
function throws on synchronous code (before the first await keyword) -- does
that result in an asynchronously rejected promise or a synchronous exception?

~~~
minitech
It results in a rejected promise. (The other behaviour would be a bit
inconsistent/annoying.)

------
Bahamut
I have one major misgiving about async-await - the regression in needing to do
a try-catch if one isn't isn't a test situation. This is a terrible syntax to
have to write to handle this.

That said, async functions also introduce a fundamental language shift in how
one parses JS. One can now block execution to return a value, but no longer
know if the innards of a function is blocking, which could mean that your
function execution is blocked by an async execution. Instead of what one may
know as async by looking at a promise or any other similar construct for
handling async flow like observables, this will be the source of many bugs in
developers' code as we shift in mindset, should this become popular. This
would definitely improve readability of code written using continuation
passing style though.

Minus the awful try-catch, I'm not necessarily against async-await being the
norm, but its broad effects on how async code will be written should be
recognized, especially considering that it doesn't solve a fundamental issue
like something like observables do.

~~~
pitaj
> One can now block execution to return a value, but no longer know if the
> innards of a function is blocking, which could mean that your function
> execution is blocked by an async execution.

Huh? I think you're misunderstanding how these functions work. You can't call
an async function from a normal function and have it block the normal
function. You specifically have to await the Promise returned by any async
function.

~~~
egeozcan
> You specifically have to await the Promise returned by any async function

I just wanted to add (may help others): And you can only do that from within
an async context (currently just the body of an async function).

------
yladiz
Am I alone in the boat that feels that the way that async/await is implemented
in JS is a little wonky? I kind of prefer that you can do `await
asyncFunc(...)` without having to denote the function itself as `async`, but I
don't like that you can just call the `asyncFunc` without `await` and it would
still potentially do something. In Python, when you `await` something, it
actually runs the code, whereas running the function by itself just returns a
Future that hasn't been started.

I feel like it's less difficult to shoot yourself in the foot with Python's
implementation, because you know that if you're calling an asynchronous
function, you have to `await` it or it won't work and won't have side effects.
In JS, you could call the async function without awaiting it and it could have
side effects which could produce subtle bugs that aren't easy to find.

------
fergie
Still not entirely sure what the big win with async/await is. Is it just a
readability thing? Is there one "killer" case that demonstrates its
superiority over callbacks?

~~~
pjmlp
Yes, you can match async/wait with generators thus using them for monad
computations in Javascript.

Think of async as return and await as bind.

~~~
fergie
"you can match async/wait with generators thus using them for monad
computations in Javascript"

I hear the words you are saying, I just cant visualise the concept. Could you
ELI5, or post an example?

~~~
pjmlp
Yes, check Bodil Stokke's presentation, The Miracle of Generators, at GOTO
2016.

[https://www.youtube.com/watch?v=6mCkLZ0cwAI](https://www.youtube.com/watch?v=6mCkLZ0cwAI)

~~~
fergie
OK- so basically: async/await, when used with generators and promises, allows
monads.

------
ilostmykeys
Why would we want to mix async and sync behavior in one cognitive space? That
seems counter evolutionary.

~~~
pacomerh
Finer control?. Synced behavior is easier to understand and organize
logically. You have the option to write it like a book and execute things
"concurrently" (considering its really single threaded in JS).

~~~
ilostmykeys
Single threaded concurrency is not the same as synchronous/sequential
execition. You and TC39 folks are telling us that mixing sync and async
behavior in the same cognitive space is good? Amazing. Async handling should
be in its own cognitive space.

------
mark242
Dear Javascript coders:

If you wind up writing the word "await" in your codebase more than once,
you're doing it wrong. You will quickly see how futures/promises wind up
taking over all of your code. This is a very good thing. You shouldn't need to
block, ever.

Sincerely,

Scala coders

~~~
mehwoot
Am I missing something? Await doesn't block. It's just syntactic sugar for
Promise.then(() => {}) without having to go down into callback hell.

It makes code more readable and easier to write, but doesn't fundamentally
change how it is working under the hood, as far as I am aware.

~~~
mark242

      var txt = await read();
      // This code is blocked until read() completes.
      console.log(txt);

~~~
solipsism
That's not what blocking means.

~~~
c-smile
Well, it depends...

async function is blocked on await statement, after all that's why it has such
a name.

It does not block the whole VM but task (async function) is effectively
blocked for an observer inside it.

~~~
solipsism
Yes but when you talking about async/await, "blocking" means "blocking the
thread". And this is very clearly what mehwoot meant.

