Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
ES6 generators in depth (2ality.com)
52 points by jakerella86 on March 30, 2015 | hide | past | favorite | 24 comments


A very in-depth post!

As Python has had generators for years already there is plenty of resources out there for the curious that translate well to ES6[0].

[0] http://www.dabeaz.com/coroutines/


His work is great! Linked to from the blog post...


Here is another deep explanation of generators, by Kyle Simpson:

https://github.com/getify/You-Dont-Know-JS/blob/master/async...

Both of them are really good, and come at it from slightly different angles.


And if you follow them on Twitter there are some good conversations back and forth. ;)


There is a GitHub repo too --> https://github.com/rauschma/generator-examples


I want to like generators for asynchronous code, but the one thing that disappoints me about generators is how awkward it is to write code that does the same as an async.auto

I use async.auto because of the ease of adding new asynchronous functions that depend on one or more other asynchronous functions having been executed beforehand.

Simply put you can break up a task into steps that depend on each other, and the steps run whenever all their dependencies have been executed. You don't have to worry about whether the functions run in series, or parallel, you just define that one function depends on another and it just works.

I have yet to see a promise example, or a generator example that had the combination of maintainability and legibility that an async.auto has. What I really want to see is a reasonably complicated task that has say 8 or more asynchronous steps mocked out in generators. Say something like:

Post a social item

1) Write social item to database

2) Write reference to social item in feed of person who posted item

3) Fetch friends of user who posted item

4) Fetch notification settings of each friend

5) Add a reference to the social item to each friend's personal activity stream

6) Based on notification settings of each user send an email alerting each friend of the event

7) Invalidate activity stream cache key for poster, and friends

In this flow:

1 & 3 can run in parallel at the start as they don't depend on anything

2 & 5 can run as soon as 1 is finished as they depend on the ID of the object in #1

4 & 5 can run as soon as 3 is finished as they depend on the friend list

6 can run as soon as 4 is done as it needs to know who to email and who not to email

7 can run as soon as 2 & 5 are done as the streams must be updated before the cache can be cleared

With async.auto it is easy to create 7 async functions and define the dependencies, then sit back and watch it run efficiently and magically. Later if you need to add more actions it is easy to insert another function, define what it depends on and see it working.

I still don't understand how to do something like this with generators, and none of the examples I've seen so far is complex enough, nor do they seem to solve this problem in a format as clean as async.auto


I didn't realize they doubled as both iterables and observables. Being able to pass a value in is a useful trick, although it looks a bit annoying to forward passed in values *due to error/return requiring try-catch shenanigans).


Amazingly in depth post!

I'm sad when programming languages have to reach for new keywords and syntax to add features.

`function*` is difficult to google for, and doesn't have any human readable hints for somebody to understand.


JavaScript is constrained by backwards compatibility. That’s why the ideal solution, the keyword `generator`, wasn’t possible.


This can't be about backwards compatibility. If it was, they wouldn't have been able to add 'yield, 'await' etc.

I don't agree the keyword "generator" would have been ideal. It wouldn't work when using 'enhanced object literals' [1], where you can declare a method without even using the keyword "function". In this case, if you want the method to be a generator, you can just put an asterisk in front of its name, so it's consistent with the "function*" syntax.

[1] https://babeljs.io/docs/learn-es6/#enhanced-object-literals


FYI, "yield" has been a reserved word since ES5 and "await" is becoming reserved in ES6 (for eventual use in ES7): https://mathiasbynens.be/notes/reserved-keywords

It seems like a word must be reserved for at least one ES version prior to it being used.


What about the "yield" keyword?


It's only valid as a keyword within the `function*` block, so the parser can treat it as an identifier elsewhere. I haven't read the detailed spec, so I'm not sure that this is the standard behavior, but this would be a way to preserve complete backward compatability.


Yes, that’s how it works. `yield` is only reserved in ES5 strict mode. But due to it only being a keyword inside generators, there are no problems in non-strict mode.


Why do you think the current syntax is more backwards-compatible? Vanilla ES5 parsers complain loudly when seeing "function *".


It's the other way around. ES6 needs to support loading ES5 content. They can't make 'generator' a keyword because it was a perfectly fine variable name in ES5.


You are right. My bad.


That would be considered "forward-compatible".


which is strange, considering the `async` keyword in upcoming versions.


AFAICT, `async function` is OK, because you combine a keyword with something that is contextually turned into a keyword. With a single non-keyword that isn’t possble. For example, the following code (a hypothetical ES6 anonymous generator expression) could be an ES5 function call followed by a code block.

    generator (a, b, c) {
        ···
    }


That's why it wasn't included in the ecmascript 6 draft. In es6, "async" and "await" are future-reserved keywords. It's kind of a process of marking variables named "async" as deprecated. The spec authors have to balance compatibility with making the language pleasant to use.


Is there even any situation where "async function(..." or "generator function(..." is currently valid syntax?


I don't think googling is much of an issue here. Unless you're talking about the very first occasion that someone sees "function*", then OK, they can't google for that easily... But they can google "function with astersik" or something and they'll find out it's called a "generator", and use that in future.


An unpopular opinion on a post about JavaScript maybe, but C#, Python, and others have implemented generators with no extra syntax because of an actual type system aside from "object, number, string, bool".




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: