generators functions ecmascript javascript node.js generator yield co

functions - javascript generators



Comprender el flujo de código con rendimiento/generadores (2)

Aparentemente, yield es azúcar sintáctica para envolver a qué vuelve en una devolución de llamada y asignar el valor del resultado de manera apropiada (y al menos en el caso de co, lanzar el argumento de error a la devolución de llamada)

No, el yield no es azúcar sintáctico. Es el elemento de sintaxis central de los generadores. Cuando se crea una instancia de ese generador, puede ejecutarlo (invocando .next() en él), y eso devolverá el valor que fue return o yield . Cuando se yield el generador, puede continuar más tarde al llamar a .next() nuevamente. Los argumentos a next serán el valor que devuelve la expresión de rendimiento dentro del generador.

Solo en el caso de co , esas cosas de devolución de llamada asincrónica (y otras cosas ) se manejan "apropiadamente" para lo que se consideraría natural en una biblioteca de flujo de control asíncrono.

¿Qué aspecto tiene el hecho cuando se utiliza el rendimiento?

El ejemplo de función de thread del artículo que lees te da una buena impresión de esto:

function thread(fn) { var gen = fn(); function next(err, res) { var ret = gen.next(res); if (ret.done) return; ret.value(next); } next(); }

En su código, yield produce el valor de la expresión read("file") del generador cuando se ejecuta. Esto se convierte en la ret.val , el resultado de gen.next() . A esto, se pasa la next función: una devolución de llamada que continuará el generador con el resultado que se le pasó. En el código de su generador, parece que la expresión de yield devuelve este valor.

Una versión "desenrollada" de lo que sucede podría escribirse así:

function fn*() { console.log( yield function (done) { fs.readFile("filepath", "file", done); } ); } var gen = fn(); var ret1 = gen.next(); var callasync = ret1.value; callasync(function next(err, res) { var ret2 = gen.next(res); // this now does log the value ret2.done; // true now });

He leído varios ejemplos de código usando generadores de JavaScript como este . El bloque de uso de generador más simple que puedo encontrar es algo así como:

function read(path) { return function (done) { fs.readFile(path, "file", done); } } co(function *() { console.log( yield read("file") ); })();

Esto realmente imprime el contenido del file , pero mi hangup es donde se llama done . Aparentemente, yield es azúcar sintáctica para ajustar lo que devuelve en una devolución de llamada y asignar el valor de resultado de manera apropiada (y al menos en el caso de co , lanzar el argumento de error a la devolución de llamada). ¿Mi comprensión de la sintaxis es correcta?

¿Qué aspecto tiene el done cuando se utiliza el yield ?


Publiqué una explicación detallada de cómo funcionan los generadores aquí .

En una forma simplificada, su código podría verse así sin co (no probado):

function workAsync(fileName) { // async logic var worker = (function* () { function read(path) { return function (done) { fs.readFile(path, "file", done); } } console.log(yield read(fileName)); })(); // driver function nextStep(err, result) { try { var item = err? worker.throw(err): worker.next(result); if (item.done) return; item.value(nextStep); } catch(ex) { console.log(ex.message); return; } } // first step nextStep(); } workAsync("file");

La parte del controlador de workAsync itera de workAsync asíncrona a través del objeto del generador, llamando a nextStep() .