Introducción:

Nota: Voy a escribir una serie de artículos sobre generadores y código asíncrono lineal para los que no sepan de qué va todo esto.
Update: Generadores.

Recientemente me he enterado de que ya han implementado generadores en el bleeding_edge del motor de javascript de google V8. ¿Qué implicaciones tiene esto? Código asíncrono lineal, limpio y elegante en el servidor sin cosas raras.

La tarea del proyecto V8:
https://code.google.com/p/v8/issues/detail?id=2355#c22

El blog del tío que ha hecho la implementación:
http://wingolog.org/archives/2013/05/08/generators-in-v8

Así que esta tarde, nada más llegar de trabajar, me he puesto manos a la obra y me lo he montado todo para empezar a usarlo.

Prueba de concepto:

Lo primero he montado una prueba de concepto y me he montado mi propia función spawn para ver que funcionaba y comprender completamente todo el flujo, que se encarga de ir ejecutando las promesas y retomando el flujo cuando se completan. Aquí un ejemplo (las promesas que uso son las Promises/A ( http://wiki.commonjs.org/wiki/Promises ) que usa Q):
https://docs.google.com/file/d/0B4Qu_52vHH3jR3NkclIzaGwxMU0/view

El ejemplo se puede ejecutar con Node.JS v0.11.2:

node --harmony sample_async_generators2.js

Al final la idea será usar task.js: http://taskjs.org/

Typescript:

Básicamente todos mis proyectos node los tengo usando typescript. Así que lo siguiente que he investigado ha sido la forma de hacerlo funcionar en typescript. Typescript no soporta la sintaxis function*() ni yield, así que mientras dan soporte, he abierto una tarea y he diseñado un apaño para usarlo.

http://typescript.codeplex.com/workitem/1076
http://typescript.codeplex.com/workitem/38

Cliente

En el cliente se puede usar también generadores, convirtiendo el javascript con el traceur-compiler de google.

¿Cómo se ve el código?

Nótese que sin el async, todo el tema de obtener datos asíncronos se haría con callbacks cutres o con promise.then, propagando los errores pasando el error como parámetro. Aquí hay un try, catch, y todos los errores tanto generados en el controlador (mientras se genera la promesa o cuando se hace un promise.reject) como en los modelos, acaban en el catch. Con lo que el código queda lineal y extremadamente limpio.