How yield will transform Node

Node v0.11.2 was released recently, and with it support for v8 generators. Generators can be hard to grasp, but essentially they're decorated functions that you can execute multiple times and resume execution at different points inside the function. What this means in practice is that we can get rid of the callback hell that has plauged node applications, and write code in a synchronous style, while it's executed asynchronously behind the scenes. A code example is worth a thousand words, so let's dive right in. We're going to need Node v0.11.2, which you can easily install with nvm. We're going to use a promise based server called Mach, and a promise library called Q. Install both of those with npm if you haven't already. Since we're using bleeding edge v8 features, you'll need to pass the flag through to Node whenever you invoke it. Let's define a function that takes an amount in milli Read more

maccaw

Q is definitely one of the slower promises libraries, so if performance is a concern it might be worth trying another one. Promises in general are going to be slower than pure callbacks (since there's more of a stack), but the difference is fairly negligible.

Since yield is basically just syntactical sugar, I think it'll be just as fast as using plain promises. Will need to do a test to say definitively though.

I was using node-fibers before yield was around to get the same behavior, and that definitely had a huge performance impact.

maccaw

Any questions about the post and I'll be happy to answer them here.

jessepollak

how does yield handle error responses? for instance if we think about a jQuery-esque library where you could use yield AJAX requests, would you need to do an if statement to check if the object error'd and then handle that accordingly or would there be some other mechanism...

sorry if that's kind of vague, it was just the first thing that popped into my mind.

maccaw

It's a good question. As far as I can tell you can't try/catch errors easily. Errors will be propagated up to Q.async, which handles them [1], and rejects the promise.

if an error is thrown in the generator, it propagates through every following yield until it is caught, or until it escapes the generator function altogether, and is translated into a rejection for the promise returned by the decorated generator.

[1] - https://github.com/kriskowal/q/blob/master/q.js#L1192

domenic

Actually, the story is much happier than that. Q.async transforms promise rejections into calls to generator.throw 1, so inside the generator body you can use try/catch like you'd expect:

app.run(Q.async(function *(request) {
  try {
    var body = yield request.parseContent();
    return JSON.stringify(body);
  } catch (e) {
    return e.message;
  }
}));
joeybaker

How's performance? Q has a reputation for being slick, but slower than callbacks. Does yield help in any way?

jsmith

I think you should be able to shim/extend forEach to support them, but yes I agree - it's sad not to have this at the language level.

aaronj1335

it seems like most of the buzz around generators in es6 has been in reference to async control flow. i came from a python background, so this surprised me a bit. the most common use case of generators in python is for lazy iteration. the same way, for instance, node.js streams allow you to process undetermined-sized data in chunks, generators are used in python for incremental processing of sequences.

but javascript doesn't seem to have the same support baked into the language to enable this. for example, for…in statements in python use generators under the hood. will javascript have the same language support baked in? right now the latest spidermonkey allows iteration over generators with for..in, but v8 does not. i'm a bit worried that we'll have this great language feature that we'll only be able to use with libraries (like this: https://github.com/aaronpowell/linq-in-javascript), similarly to how we needed (and still need) underscore-like libraries for simple iteration.