2010-11-08 13 views
47

C'è un modo per ottenere generators in node.js?node.js supporta yield?

Attualmente sto fatele sembrare con callback, ma devo ricordare di controllare la risposta della richiamata all'interno della mia funzione di generatore che crea un sacco di if (callback(arg) === false) return;

voglio qualcosa di simile in Python:

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

che io sto facendo in nodo come questo:

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

Forse qualcosa di simile coffeescript potrebbe aiutare?

+0

Probabilmente il coffeescript non riceverà generatori in qualsiasi momento: https://github.com/jashkenas/coffee-script/issues/issue/983#issue/983/comment/639738 – Amir

+1

Nota anche JavaScript utilizza camelCase per le funzioni, ad esempio 'doSomething', non' do_something' – mikemaccana

risposta

23
+4

ma la versione corrente è 'v0.10.24', sono confuso. – Michelle

+2

L'ultima versione stabile è v.0.10.24, ma è sempre possibile ottenere una versione instabile [qui] (http://nodejs.org/dist/) (attualmente v0.11.10). Le versioni sono sempre annunciate nel nodo [blog] (http://blog.nodejs.org/release/) (con changelog). I documenti v0.11.10 sono [qui] (http://nodejs.org/dist/v0.11.10/docs/api/). Ciò non avrebbe dovuto essere difficile da trovare, dalla [Home page Nodejs.org] (http://nodejs.org)> [Download] (http://nodejs.org/download/)> [Altre versioni] (http://nodejs.org/dist/). –

+0

Non riesco a farli funzionare, anche con il flag '--harmony' nel nodo v0.10.29. – mpen

0

Aggiornamento 2014: il nodo supporta ora i callback. Quello che segue è un post del 2010.


È necessario utilizzare le richiamate. Se la funzione fa qualcosa in modo asincrono, si potrebbe anche voler una richiamata continuazione (continuazione è una brutta parola, dal momento che significa anche un'altra cosa, ma si ottiene il mio 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... 
}) 

Aggiornato con esempio di codice

L'ho capovolto, in modo che ritorni vero su completo (poiché null, falso e non definito valgono comunque per falso).

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

Ma la mia funzione 'primi' è piena di' if (callback (arg) === false) return; ' invece di solo 'yield arg'. Dovrebbe essere così brutto? –

+1

'do {/ * imposta i dati di callback * /} while (callback (arg)); seguito() '? Ricorda che non è così importante come appare all'interno della funzione, a patto che l'interfaccia e l'output siano buoni. –

+0

oh, e per quanto riguarda la funzione di primi (presumo che stai facendo un po 'di complicato nidificazione), dovrai codificarlo in modo tale da poter rilasciare tutto, passare alla richiamata, quindi ricominciare dall'iterazione successiva (usando le variabili temporanee per mantenere lo stato), o dovrai semplicemente convivere con le linee di callback multiple. –

2

Sì e no.

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

Come si vede, è possibile implementare qualcosa come uno che utilizza chiusure, ma non ha generatori nativi.

2

Il issue che propone i generatori in v8 è stato recentemente accettato dal membro del progetto v8.
Si prega di votare lì per rendere yield avverarsi.

4

È possibile utilizzare i generatori di Node.js, ma solo in 0.11+. Node.js 0.12 (stabile) è ora disponibile. Aggiungi --harmony_generators o --harmony ai parametri della riga di comando del nodo per abilitarlo.

Con Traceur, è possibile compilare JavaScript avanzato su vanilla JavaScript. Potresti creare un caricatore per il nodo.js che fa questo al volo. Poiché gira su e compila su JavaScript vaniglia, viene eseguito in node.js < 0.11 e nel browser.

Facebook ha sviluppato una versione più leggera che supporta solo i generatori, denominata Regenerator. Funziona in modo simile a Traceur.

3

Apparentemente non nella versione stabile attuale. Puoi comunque ottenere lo stesso usando fibre-nodo + promesse.

Qui è la mia realizzazione:

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(); 
}; 

E un codice di esempio su come funziona: (query.find restituisce una promessa)

 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

potresti inserire anche il codice sorgente per la query? funzionerà con qualsiasi sistema di callback? – kroe

Problemi correlati