Diferencia entre rendimiento async/await y ES6 con generadores
Estaba leyendo este fantástico artículo -
Https://www.promisejs.org/generators /
Y resalta 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 hipotetizo es más o menos la forma en que la palabra clave async se implementa con async/await
. Así que la pregunta es, si ese es el caso, entonces ¿cuál es la diferencia entre la palabra clave await
y la palabra clave yield
? Does await
always turn algo en una promesa, mientras que yield
no hace tal garantía? ¡Esa es mi mejor suposición!
También puedes ver cómo async/await es similar a yield con generadores en este artículo donde describe la función 'spawn': https://jakearchibald.com/2014/es7-async-functions /
6 answers
yield
puede considerarse que es el componente básico de await
. yield
toma el valor que se le ha dado 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 yield
(2), o un error que parecerá ser arrojado por la expresión yield
(3).
async
-await
puede considerarse que utiliza yield
. En (1) la persona que llama (es decir, el async
-await
conductor-similar para la función que ha publicado) envolverá el valor en una promesa utilizando un algoritmo similar a new Promise(r => r(value)
(nota, no Promise.resolve
, pero eso no es gran cosa). Entonces espera que la promesa se resuelva. Si cumple, pasa el valor cumplido de nuevo en (2). Si rechaza, arroja la razón de rechazo como un error en (3).
Así que la utilidad de async
-await
es esta maquinaria que utiliza yield
para desenvolver el valor producido como una promesa y pasar su valor resuelto de nuevo, repitiendo hasta el la función devuelve su valor final.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-24 11:23:36
Bueno, resulta que hay una relación muy estrecha entre async/await y los generadores. Y creo que async / await siempre se construirá en generadores. Si nos fijamos en la forma en que Babel transpila async / await:
Babel toma esto:
this.it('is a test', async function () {
const foo = await 3;
const bar = await new Promise(function (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(function (resolve) {
resolve('7');
});
const baz = bar * foo;
console.log(baz);
}));
Haz las cuentas.
Esto hace que parezca que la palabra clave async es solo esa función de envoltura, pero si ese es el caso, entonces await se convierte en yield, probablemente habrá un poco más a la imagen más adelante cuando se convierten en nativos.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-27 08:10:35
¿Cuál es la diferencia entre la palabra clave
await
y la palabra claveyield
?
La palabra clave await
solo se usa en async function
s, mientras que la palabra clave yield
solo se usa en generator function*
s. Y esas son obviamente diferentes también - una devuelve promesas, la otra devuelve generadores.
¿
await
siempre convierte algo en una promesa, mientras queyield
no hace tal garantía?
Sí, await
llamará a Promise.resolve
en el valor esperado.
yield
solo produce el valor fuera del generador.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-24 11:26:10
Pruebe este programa de prueba que utilicé para entender await/async 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');
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-14 05:20:32
Tldr;
Utilice Async / Await el 99% de las veces sobre generadores. ¿Por qué?
Async / Await reemplaza directamente el flujo de trabajo más común de las cadenas de promesa permitiendo que el código sea declarado como si fuera sincrónico, simplificándolo dramáticamente.
Los generadores resumen el caso de uso en el que llamaría a una serie de operaciones asincrónicas que dependen unas de otras y que eventualmente estarán en un estado "hecho". El ejemplo más simple sería la búsqueda de resultados que eventualmente devuelva el último conjunto, pero solo llamaría a una página según sea necesario, no inmediatamente en sucesión.
Async / Await es en realidad una abstracción construida sobre generadores para facilitar el trabajo con promesas.
Ver una explicación muy detallada de Async / Await vs. Generators
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-23 22:50:21
En muchos sentidos, los generadores son un superconjunto de async/await. En este momento async/await tiene trazas de pila más limpias que co, la lib basada en generador similar a async/await más popular. Puede implementar su propio tipo de async / await usando generadores y agregar nuevas características, como soporte incorporado para yield
en no promesas o construirlo en observables RxJS.
Así que, en resumen, los generadores le dan más flexibilidad y las bibliotecas basadas en generadores generalmente tienen más características. Pero async / await es un núcleo parte del lenguaje, está estandarizado y no cambiará bajo ti, y no necesitas una biblioteca para usarlo. Tengo una entrada de blog con más detalles sobre la diferencia entre async/await y generators.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-03 16:03:01