¿Cuál es la diferencia entre las promesas de JavaScript y la espera asíncrona?
He estado usando ECMAScript 6 y ECMAScript 7 (gracias a Babel) en mis aplicaciones, tanto móviles como web.
El primer paso obviamente fue alcanzar los niveles ECMAScript 6. Aprendí muchos patrones asíncronos, las promesas (que son realmente prometedoras), los generadores (no estoy seguro de por qué el símbolo *), etc. De estos, las promesas se adaptaron bastante bien a mi propósito. Y los he estado usando bastante en mis aplicaciones.
Aquí hay un ejemplo/pseudocódigo de cómo he implementado una promesa básica:
var myPromise = new Promise(
function (resolve,reject) {
var x = MyDataStore(myObj);
resolve(x);
});
myPromise.then(
function (x) {
init(x);
});
A medida que pasó el tiempo, me encontré con las características de ECMAScript 7, y una de ellas fue ASYNC
palabras AWAIT
clave/funciones. Estos en conjunto hacen grandes maravillas. He comenzado a reemplazar algunas de mis promesas conasync & await
. Parecen agregar un gran valor al estilo de programación.
Nuevamente, aquí hay un pseudocódigo de cómo se ve mi función asíncrona de espera:
async function myAsyncFunction (myObj) {
var x = new MyDataStore(myObj);
return await x.init();
}
var returnVal = await myAsyncFunction(obj);
Dejando a un lado los errores de sintaxis (si los hay), lo que siento es que ambos hacen exactamente lo mismo. Casi he podido reemplazar la mayoría de mis promesas con async, espera.
¿Por qué se necesita async,await cuando las promesas hacen un trabajo similar?
¿Async,await resuelve un problema mayor? ¿O fue simplemente una solución diferente al infierno de las devoluciones de llamadas?
Como dije antes, puedo usar promesas y async,await para resolver el mismo problema. ¿Hay algo específico que async espera resuelto?
Notas adicionales:
He estado usando ampliamente async, awaits y promesas en mis proyectos de React y módulos de Node.js. React especialmente fue uno de los primeros y adoptó muchas características de ECMAScript 6 y ECMAScript 7.
¿Por qué se necesita async,await cuando Promises hace un trabajo similar? ¿Async,await resuelve un problema mayor?
async/await
simplemente le brinda una sensación de sincronía con el código asincrónico. Es una forma muy elegante de azúcar sintáctico.
Para consultas simples y manipulación de datos, las Promesas pueden ser simples, pero si te encuentras con escenarios donde hay manipulación de datos compleja y todo eso, es más fácil entender lo que sucede si el código simplemente parece sincrónico (para decirlo de otra manera, la sintaxis en sí misma es una forma de "complejidad incidental" que async/await
puede eludirse).
Si está interesado en saberlo, puede usar una biblioteca como co
(junto con los generadores) para brindar el mismo tipo de sensación. Cosas como esta se han desarrollado para resolver el problema que async/await
finalmente se resuelve (de forma nativa).
Async/Await proporciona una sintaxis mucho mejor en escenarios más complejos. En particular, cualquier cosa que tenga que ver con bucles u otras construcciones como try
/ catch
.
Por ejemplo:
while (!value) {
const intermediate = await operation1();
value = await operation2(intermediate);
}
Este ejemplo sería considerablemente más complicado simplemente usando Promises.
¿Por qué se necesita async,await cuando Promises hace un trabajo similar? ¿Async,await resuelve un problema mayor? ¿O fue simplemente una solución diferente al infierno de las devoluciones de llamadas? Como dije antes, puedo usar Promises y Async, espero resolver el mismo problema. ¿Hay algo específico que resolvió Async Await?
Lo primero que debe comprender es que la sintaxis async
/ await
es solo azúcar sintáctico que está destinado a aumentar las promesas. De hecho, el valor de retorno de una async
función es una promesa. async
/ await
sintaxis nos da la posibilidad de escribir asíncrono de forma síncrona. Aquí hay un ejemplo:
Encadenamiento de promesas:
function logFetch(url) {
return fetch(url)
.then(response => response.text())
.then(text => {
console.log(text);
}).catch(err => {
console.error('fetch failed', err);
});
}
Async
función:
async function logFetch(url) {
try {
const response = await fetch(url);
console.log(await response.text());
}
catch (err) {
console.log('fetch failed', err);
}
}
En el ejemplo anterior, se await
espera a que la promesa ( fetch(url)
) se resuelva o rechace. Si se resuelve la promesa el valor se almacena en la response
variable, y si se rechaza la promesa arrojaría un error y así entraría al catch
bloque.
Ya podemos ver que usar async
/ await
podría ser más legible que el encadenamiento de promesas. Esto es especialmente cierto cuando aumenta la cantidad de promesas que utilizamos. Tanto el encadenamiento de promesas como async
/ await
resolver el problema del infierno de devolución de llamada y el método que elija es una cuestión de preferencia personal.
Async/await puede ayudar a que su código sea más limpio y legible en los casos en que necesite un flujo de control complicado. También produce código más fácil de depurar. Y hace posible manejar errores sincrónicos y asincrónicos con solo try/catch
.
Recientemente escribí esta publicación mostrando las ventajas de async/await sobre las promesas en algunos casos de uso comunes con ejemplos de código: 6 razones por las que JavaScript Async/Await arruina las promesas (Tutorial)