2010-11-08 16 views
47

¿Hay alguna forma de obtener generators en node.js?¿Admite node.js el rendimiento?

Actualmente estoy fingiendo con devoluciones de llamada, pero tengo que recordar comprobar la respuesta de la devolución de llamada dentro de mi función de generador que crea una gran cantidad de if (callback(arg) === false) return;

quiero algo así como en Pitón:

for p in primes(): 
    if p > 100: break 
    do_something(p) 

la que estoy haciendo en el nodo de la siguiente manera:

primes(function(p) { 
    if (p > 100) return false; 
    do_something(p) 
}); 

tal vez algo como coffeescript podría ayudar?

+0

Coffeescript probablemente no obtenga generadores pronto: https://github.com/jashkenas/coffee-script/issues/issue/983#issue/983/comment/639738 – Amir

+1

También tenga en cuenta que JavaScript utiliza camelCase para funciones, es decir 'doSomething', not' do_something' – mikemaccana

Respuesta

23
+4

pero su versión actual es 'v0.10.24', estoy confundido. – Michelle

+2

La última versión estable es v.0.10.24, pero siempre puede obtener una versión inestable [aquí] (http://nodejs.org/dist/) (actualmente v0.11.10). Los lanzamientos siempre se anuncian en el nodo [blog] (http://blog.nodejs.org/release/) (con changelog). Los documentos v0.11.10 son [aquí] (http://nodejs.org/dist/v0.11.10/docs/api/). Eso no debería haber sido difícil de encontrar, desde la [página de inicio de Nodejs.org] (http://nodejs.org)> [Descargas] (http://nodejs.org/download/)> [Otras publicaciones] (http://nodejs.org/dist/). –

+0

No puedo hacer que funcionen, incluso con el indicador '--harmony' en el nodo v0.10.29. – mpen

0

Actualización 2014: el nodo admite devoluciones de llamada ahora. La siguiente es una publicación de 2010.


Debe utilizar devoluciones de llamada. Si la función hace algo de forma asíncrona, es posible que también desea una devolución de llamada de continuación (Continuación es una mala palabra, ya que también significa otra cosa, pero que mi punto.)

primes(function(p) { 
    if (p > 100) return false // i assume this stops the yielding 
    do_something(p) 
    return true // it's also better to be consistent 
}, function(err) { // fire when the yield callback returns false 
    if (err) throw err // error from whatever asynch thing you did 
    // continue... 
}) 

Actualizado con ejemplo de código

Lo volteé, para que devuelva verdadero en completo (ya que nulo, falso e indefinido todos evalúan a falso de todos modos).

function primes(callback) { 
    var n = 1, a = true; 
    search: while (a) { 
    n += 1; 
    for (var i = 2; i <= Math.sqrt(n); i += 1) 
     if (n % i == 0) 
     continue search; 
    if (callback(n)) return 
    } 
} 

primes(function(p) { 
    console.log(p) 
    if (p > 100) return true 
}) 
+0

Pero mi función 'primes' está llena de' if (callback (arg) === false) return; ' en lugar de solo 'yield arg'. Se supone que es tan feo? –

+1

'do {/ * configura los datos de devolución de llamada * /} while (callback (arg)); continuación() '? Recuerde que no es tan importante como se ve dentro de la función, siempre que la interfaz y la salida sean buenas. –

+0

oh, y con respecto a su función de primos (supongo que está haciendo una anidación complicada allí), tendrá que codificarlo de tal manera que pueda soltar todo, pasar a devolución de llamada, y luego comenzar de nuevo en la siguiente iteración (utilizando variables temporales para mantener el estado), o simplemente tendrá que vivir con las múltiples líneas de devolución de llamada. –

2

Sí y no.

var myGen = (function() { 
    var i = 0; 
    return function() { 
     i++; return i; } 
})(); 
var i; 
while ((i = myGen()) < 100) { 
    do something; } 

Como ve, puede implementar algo así como uno usando cierres, pero no tiene generadores nativos.

2

El issue proponiendo generatiors en v8 ha sido aceptado recientemente por el miembro del proyecto v8.
Por favor, vote allí para hacer yield hecho realidad.

4

Puede utilizar generadores de Node.js, pero sólo en 0.11+. Node.js 0.12 (estable) ahora está disponible. Agregue --harmony_generators o --harmony a los parámetros de línea de comando del nodo para habilitarlo.

Con Traceur, puede compilar JavaScript avanzado para JavaScript vainilla. Usted podría hacer un cargador para el nodo.js que hace esto sobre la marcha. Desde que se ejecuta y se compila con JavaScript vandalo, se ejecuta en node.js < 0.11 y también en el navegador.

Facebook ha desarrollado una versión más ligera que solo admite generadores, llamada Regenerator. Funciona de manera similar a Traceur.

3

Aparentemente no en la versión estable actual. Sin embargo, puede lograr el mismo uso de fibras de nodo + promesas.

Aquí es mi aplicación:

var fiber = require('fibers'); 

module.exports.yield = function (promise) { 

    var currentFiber = fiber.current; 
    promise 
     .then(function (value) { 
      currentFiber.run(value); 
     }) 
     .otherwise(function (reason) { 
      currentFiber.throwInto(reason); 
     }); 

    return fiber.yield(); 
}; 
module.exports.spawn = function (makeGenerator) { 
    fiber(function() { 
     makeGenerator.apply(this, Array.prototype.slice.call(arguments, 1)); 
    }).run(); 
}; 

Y un código de ejemplo de cómo funciona: (query.find devuelve una promesa)

 var generators = require('./utils/generators'); 
     var query = require('./utils/query'); 

     generators.spawn(function() { 
      try { 
       var field1 = generators.yield(query.find('user', { _id : '1' })); 
       var field2 = generators.yield(query.find('user', { _id : '2' })); 
       console.log('success', field1[0]._id, field2[0]._id); 
      } 
      catch (e) { 
       console.error('error', e); 
      } 
     }); 
+0

¿podría también publicar el código fuente para la consulta? ¿Funcionará con cualquier sistema de devolución de llamada? – kroe

Cuestiones relacionadas