que generador for es6 javascript node.js ecmascript-6 generator ecmascript-next

generador - symbol iterator javascript



Diferencia entre asíncrono/espera y rendimiento ES6 con generadores (6)

¿Cuál es la diferencia entre la palabra clave de await y la palabra clave de yield ?

La palabra clave await solo se debe usar en async function , mientras que la palabra clave de yield solo se debe usar en function* generadoras function* s. Y estos también son obviamente diferentes: uno devuelve promesas, el otro devuelve generadores.

¿La await siempre convierte algo en una promesa, mientras que el yield no ofrece tal garantía?

Sí, Promise.resolve llamará a Promise.resolve en el valor esperado.

yield solo produce el valor fuera del generador.

Estaba leyendo este fantástico artículo.

https://www.promisejs.org/generators/

y destaca claramente esta función, que es una función auxiliar para manejar las funciones del generador:

function async(makeGenerator){ return function () { var generator = makeGenerator.apply(this, arguments); function handle(result){ // result => { done: [Boolean], value: [Object] } if (result.done) return Promise.resolve(result.value); return Promise.resolve(result.value).then(function (res){ return handle(generator.next(res)); }, function (err){ return handle(generator.throw(err)); }); } try { return handle(generator.next()); } catch (ex) { return Promise.reject(ex); } } }

lo que supongo es más o menos la forma en que la palabra clave asincrónica se implementa con async/await . Entonces la pregunta es, si ese es el caso, ¿cuál es la diferencia entre la palabra clave de await y la palabra clave de yield ? ¿La await siempre convierte algo en una promesa, mientras que el yield no ofrece tal garantía? Esa es mi mejor suposición!

También puede ver cómo async / await es similar al rendimiento con generadores en este artículo donde describe la función ''spawn'': https://jakearchibald.com/2014/es7-async-functions/


tldr;

Use Async / Await 99% del tiempo sobre Generadores. ¿Por qué?

  1. Async / Await reemplaza directamente el flujo de trabajo más común de las cadenas de promesa permitiendo que el código se declare como si fuera síncrono, simplificándolo drásticamente.

  2. Los generadores resumen el caso de uso donde llamaría a una serie de operaciones asíncronas que dependen unas de otras y eventualmente estarán en un estado "hecho". El ejemplo más simple sería buscar resultados que finalmente devuelvan el último conjunto, pero solo llamaría a una página según sea necesario, no inmediatamente en sucesión.

  3. Async / Await es en realidad una abstracción construida sobre los Generadores para facilitar el trabajo con promesas.

Vea una explicación muy detallada de Async / Await vs. Generators


Bueno, resulta que hay una relación muy estrecha entre async / wait y generadores. Y creo que async / await siempre se basará en generadores. Si observa la forma en que Babel transpila async / wait:

Babel toma esto:

this.it(''is a test'', async function () { const foo = await 3; const bar = await new Promise(resolve => resolve(''7'')); const baz = bar * foo; console.log(baz); });

y lo convierte en esto

function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { return step("next", value); }, function (err) { return step("throw", err); }); } } return step("next"); }); }; } this.it(''is a test'', _asyncToGenerator(function* () { // << now it''s a generator const foo = yield 3; // <<< now it''s yield, not await const bar = yield new Promise(resolve => resolve(7)); const baz = bar * foo; console.log(baz); }));

Tú haces los cálculos.

Esto hace que parezca que la palabra clave asíncrona es solo esa función de contenedor, pero si ese es el caso, la espera se convertirá en rendimiento, probablemente habrá un poco más en la imagen más adelante cuando se conviertan en nativos.

Puede ver más explicaciones para esto aquí: https://www.promisejs.org/generators/


En muchos sentidos, los generadores son un superconjunto de asíncrono / espera. En este momento, async / await tiene rastros de pila más limpios que co , la lib basada en el generador async / await-like más popular. Puede implementar su propio sabor de asíncrono / espera usando generadores y agregar nuevas características, como soporte integrado para yield en no promesas o construirlo en observables RxJS.

En resumen, los generadores le brindan más flexibilidad y las bibliotecas basadas en generadores generalmente tienen más funciones. Pero async / await es una parte central del lenguaje, está estandarizado y no cambiará bajo usted, y no necesita una biblioteca para usarlo. Tengo una publicación de blog con más detalles sobre la diferencia entre async / await y generadores.


Pruebe estos programas de prueba que solía entender en espera / asíncrono con promesas

Programa # 1: sin promesas no se ejecuta en secuencia

function functionA() { console.log(''functionA called''); setTimeout(function() { console.log(''functionA timeout called''); return 10; }, 15000); } function functionB(valueA) { console.log(''functionB called''); setTimeout(function() { console.log(''functionB timeout called = '' + valueA); return 20 + valueA; }, 10000); } function functionC(valueA, valueB) { console.log(''functionC called''); setTimeout(function() { console.log(''functionC timeout called = '' + valueA); return valueA + valueB; }, 10000); } async function executeAsyncTask() { const valueA = await functionA(); const valueB = await functionB(valueA); return functionC(valueA, valueB); } console.log(''program started''); executeAsyncTask().then(function(response) { console.log(''response called = '' + response); }); console.log(''program ended'');

programa 2: con promesas:

function functionA() { return new Promise((resolve, reject) => { console.log(''functionA called''); setTimeout(function() { console.log(''functionA timeout called''); // return 10; return resolve(10); }, 15000); }); } function functionB(valueA) { return new Promise((resolve, reject) => { console.log(''functionB called''); setTimeout(function() { console.log(''functionB timeout called = '' + valueA); return resolve(20 + valueA); }, 10000); }); } function functionC(valueA, valueB) { return new Promise((resolve, reject) => { console.log(''functionC called''); setTimeout(function() { console.log(''functionC timeout called = '' + valueA); return resolve(valueA + valueB); }, 10000); }); } async function executeAsyncTask() { const valueA = await functionA(); const valueB = await functionB(valueA); return functionC(valueA, valueB); } console.log(''program started''); executeAsyncTask().then(function(response) { console.log(''response called = '' + response); }); console.log(''program ended'');


yield puede ser considerado como la piedra angular de la await . yield toma el valor que se le da y se lo pasa a la persona que llama. La persona que llama puede hacer lo que quiera con ese valor (1). Más tarde, la persona que llama puede devolver un valor al generador (a través de generator.next() ) que se convierte en el resultado de la expresión de yield (2), o un error que parecerá arrojado por la expresión de yield (3).

async - await puede ser considerado para usar el yield . En (1) la persona que llama (es decir, el controlador async - await - similar a la función que publicó) envolverá el valor en una promesa utilizando un algoritmo similar al new Promise(r => r(value) (nota, no Promise.resolve , pero eso no es gran cosa). Luego espera a que se resuelva la promesa. Si se cumple, pasa el valor cumplido nuevamente a (2). Si rechaza, arroja la razón de rechazo como un error en (3).

Entonces, la utilidad de async - await es esta maquinaria que usa el yield para desenvolver el valor cedido como una promesa y devolver su valor resuelto, repitiendo hasta que la función devuelva su valor final.