Skip to content

Instantly share code, notes, and snippets.

@dyoder
Last active August 29, 2015 14:27
Show Gist options
  • Save dyoder/f598f703d9644e7627a3 to your computer and use it in GitHub Desktop.
Save dyoder/f598f703d9644e7627a3 to your computer and use it in GitHub Desktop.
15:28 < david> Dan, are you around?
15:32 < david> Well, actually this doesn't require anything dramatic, haha.
15:34 < david> I know why Tonicdev cannot use Fairmont. It lets you use the await operator from ES7 to wait on promises, but it doesn't know anything about generators. It's running Node 12 without the Harmony flag, so it's ES5 JS with that await functionality baked in because it makes things so much easier.
15:36 < david> I'm curious if you're interested in generators in Fairmont's future, since ES7 has asynchronous functions and this "await" thing. Although, does CoffeeScript support those ES7 features?
15:44 < david> It looks like work in CS is still pending, but being actively considered. https://github.com/jashkenas/coffeescript/pull/3757
15:49 < david> It's kinda weird... await and yield are similar and both need an outer, calling function. But yield's outer function must be a generator. Is one preferred over the other?
18:21 < lance> tom: cool!
19:24 < dan> david: it's a bit of a mess.
19:25 < dan> semi-coroutines with generator functions has a bit of overhead
19:25 < dan> so async-await is intended to build that into the JS engines
19:26 < dan> under the covers, i think await converts into a yield and a generator function
19:27 < dan> but it can't actually be a generator function, so a different keyword is needed
19:27 < dan> i'm not really certain why async couldn't have been introduced instead, just as we use it in fairmont
19:28 < dan> without the use of await (using just yield)
19:28 < dan> but i'm sure there's a very good reason for that
19:28 < dan> if i spent enough time studying it, that would likely become obvious
19:30 < dan> but once you stipulate that async can't operate on a generator function, you then need a different keyword
19:30 < dan> since yield can only happen from within a generator function
19:31 < dan> it's a little bit unfortunate because all our code is based on ES6 and using generators as semi-coroutines
19:31 < dan> for performance reasons i've rewritten some of that code to use normal functions and promises directly
19:32 < dan> but it's possible that we will eventually want to use async-await
19:32 < dan> or, we should use traceur/babel now and use async-await, presuming the generated code is just functions and promises
19:33 < dan> but that brings us to the issue you raised about CS support, which right now, is in the very early stages
19:33 < david> Okay.
19:33 < dan> jashkenas does not appear to have endorsed any approach
19:33 < david> yeah, incorporating babel into the build process seems like it's going to happen at some point.
19:34 < david> Well, it sounds like the function* yield vs async await should be a blog post, haha.
19:36 < david> I would hope that their reason is very strong, because it seems confusing at best and dangerous at worst to have these parallel approaches to asynchronous methods.
19:37 < david> Does it have to do with how ES6 "native" promises are specified? Are they somehow inferior to one produced by a library like when or bluebird?
19:37 < dan> david: no i think it is purely a performance thing
19:38 < dan> coroutines with generators requires a controller/manager function, that takes the yield values and then returns control back to the function
19:38 < dan> when they resolve (if the value was a promise)
19:39 < dan> this ping-pong is costly. in my benchmarks, it was like an order of magnitude slower.
19:40 < dan> however, the generator plumbing is necessary to support async-await, because it think what that does is take the manager function and compile that into the JS engine
19:40 < dan> (that is, it's written directly in C)
19:41 < dan> and the async modifier tells the compiler to treat the function much like a generator, but probably optimized somewhat to work with the manager function
19:41 < david> hmm.. And they can't do that with ES6 generators because they might not be returning a promise?
19:41 < dan> there won't be anything confusing about it because async-await will be THE way to do what we're currently doing with async (as a wrapper function) and yield
19:42 < dan> no. it's just a performance thing. if you know a generator is being used as a coroutine, you can compile it differently
19:42 < david> Oh. Okay
19:42 < dan> you can optimize for that case, especially since the controller function is already in C
19:43 < dan> what we're doing now is wrapping the generator in a JavaScript controller function (that's what async does)
19:43 < dan> but that's also why it's so slow
19:43 < dan> if the controller function is in C and the generator function could be optimized to communicate with that C function, it could potentially be much faster
19:44 < dan> maybe as fast as just hand-coding promise-logic
19:45 < david> Okay. Cool. I guess I was so excited by ES6's avoidance of callbacks that I didn't realize it ran that much more slowly.
19:48 < dan> david: most of the time it's not a big deal
19:49 < dan> but for example in fairmont's filter functions (map, select, reject, ...) i have taken out most of the generator-based code and replaced it with promises-based logic
19:50 < dan> because they're part of a general purpose library
19:50 < dan> for application-level code, though, you can do everything using generators and optimize out the stuff where it's problematic
19:51 < dan> keep in mind that, if you're using coroutines like that, it's probably because there's an I/O operation involved which is several orders of magnitude slower than the ping-ponging of manager functions
19:51 < dan> the path laid out in ES6 is very clever and very much in keeping with eich's approach to this stuff
19:52 < dan> first, make coroutines _possible_; second, (in ES7) offer an optimized implementation
19:52 < dan> optimized/standardized
19:52 < dan> (since every promise library has their own version of a controller function)
19:53 < dan> (so you can inadvertantly wind up with several controller functions in your app for no good reason other than one library did it one way and another library did it another way)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment