Dados los ejemplos de código a continuación, ¿hay alguna diferencia en el comportamiento y, de ser así, cuáles son esas diferencias?
return await promise
async function delay1Second() {
return (await delay(1000));
}
return promise
async function delay1Second() {
return delay(1000);
}
Según tengo entendido, el primero tendría manejo de errores dentro de la función asíncrona, y los errores saldrían de la Promesa de la función asíncrona. Sin embargo, el segundo requeriría un tic menos. ¿Es esto correcto?
Este fragmento es solo una función común para devolver una Promesa como referencia.
function delay(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
javascript
async-await
PitaJ
fuente
fuente

asyncde tu segundo (return promise) ejemplo.promise.then(() => nestedPromise)aplanaría y "seguiría" elnestedPromise. Es interesante cómo es diferente de las tareas anidadas en C # donde tendríamos queUnwraphacerlo. En una nota al margen, parece que lasawait somePromisellamadasPromise.resolve(somePromise).then, en lugar de solosomePromise.then, tienen algunas diferencias semánticas interesantes.Respuestas:
La mayoría de las veces, no hay una diferencia observable entre
returnyreturn await. Ambas versiones dedelay1Secondtienen exactamente el mismo comportamiento observable (pero dependiendo de la implementación, lareturn awaitversión podría usar un poco más de memoria porquePromisepodría crearse un objeto intermedio ).Sin embargo, como señaló @PitaJ, hay un caso en el que hay una diferencia: si
returnoreturn awaitestá anidado en un bloquetry-catch. Considere este ejemploEn la primera versión, la función async espera la promesa rechazada antes de devolver su resultado, lo que provoca que el rechazo se convierta en una excepción y
catchse alcance la cláusula; la función devolverá así una promesa que se resuelve en la cadena "¡Guardado!".La segunda versión de la función, sin embargo, devuelve la promesa rechazada directamente sin esperarla dentro de la función asíncrona , lo que significa que no se llama al
catchcaso y la persona que llama obtiene el rechazo.fuente
return new Promise(function(resolve, reject) { })dentro de unfor...ofbucle y luego llamarresolve()dentro del bucle después depipe()que no pausa la ejecución del programa hasta que la tubería se haya completado, como se desea, sin embargo, el usoawait new Promise(...)sí lo hace. ¿Es esta última incluso una sintaxis válida / correcta? es 'taquigrafía' parareturn await new Promise(...)? ¿Podrías ayudarme a entender por qué funciona el último y el primero no? para el contexto, el escenario es en elsolution 02de esta respuestaComo se mencionó en otras respuestas, es probable que exista un ligero beneficio en el rendimiento al dejar que la promesa brote devolviéndola directamente, simplemente porque no tiene que esperar el resultado primero y luego envolverlo con otra promesa nuevamente. Sin embargo, nadie ha hablado todavía sobre la optimización de llamadas finales .
La optimización de llamadas de cola , o "llamadas de cola adecuadas" , es una técnica que utiliza el intérprete para optimizar la pila de llamadas. Actualmente, todavía no hay muchos tiempos de ejecución que lo admitan, aunque técnicamente es parte del estándar ES6 , pero es posible que se agregue soporte en el futuro, por lo que puede prepararse para eso escribiendo un buen código en el presente.
En pocas palabras, TCO (o PTC) optimiza la pila de llamadas al no abrir un nuevo marco para una función que es devuelta directamente por otra función. En cambio, reutiliza el mismo marco.
Dado que
delay()es devuelto directamente pordelay1Second(), los tiempos de ejecución que admiten PTC primero abrirán un marco paradelay1Second()(la función externa), pero luego, en lugar de abrir otro marco paradelay()(la función interna), simplemente reutilizará el mismo marco que se abrió para la función externa. Esto optimiza la pila ya que puede evitar un desbordamiento de pila (hehe) con muy grandes funciones recursivas, por ejemplo,fibonacci(5e+25). Básicamente, se convierte en un bucle, que es mucho más rápido.PTC solo se habilita cuando la función interna se devuelve directamente . No se usa cuando el resultado de la función se modifica antes de que se devuelva, por ejemplo, si tenía
return (delay(1000) || null), oreturn await delay(1000).Pero como dije, la mayoría de los tiempos de ejecución y los navegadores aún no son compatibles con PTC, por lo que probablemente no haga una gran diferencia ahora, pero no estaría de más preparar su código para el futuro.
Lea más en esta pregunta: Node.js: ¿Hay optimizaciones para llamadas finales en funciones asíncronas?
fuente
Esta es una pregunta difícil de responder, porque depende en la práctica de cómo su transpiler (probablemente
babel) se procese realmenteasync/await. Las cosas que están claras independientemente:Ambas implementaciones deben comportarse igual, aunque la primera implementación puede tener una menos
Promiseen la cadena.Especialmente si descarta lo innecesario
await, la segunda versión no requeriría ningún código adicional del transpilador, mientras que la primera sí.Por lo tanto, desde una perspectiva de depuración y rendimiento del código, la segunda versión es preferible, aunque solo un poco, mientras que la primera versión tiene un ligero beneficio de legibilidad, ya que indica claramente que devuelve una promesa.
fuente
undefined) y el segundo devuelve unPromise.async/await, me resulta mucho más difícil razonar. @PitaJ es correcto, ambas funciones devuelven una Promesa.try-catch? En elreturn promisecaso, cualquierarejectionno sería capturado, ¿correcto, mientras que, en elreturn await promisecaso, sería correcto?awaitcada uno de estos en algún sitio de llamada, el resultado será muy diferente.aqui te dejo un codigo practico para que puedas entenderlo la diferencia
la función "x" solo es una función asíncrona que tiene otras funciones si se borrará el retorno imprime "más código ..."
la variable x es solo una función asincrónica que a su vez tiene otra función asincrónica, en la principal del código invocamos una espera para llamar a la función de la variable x, cuando se completa sigue la secuencia del código, eso sería normal para "async / await", pero dentro de la función x hay otra función asincrónica, y esta devuelve una promesa o devuelve una "promesa" permanecerá dentro de la función x, olvidando el código principal, es decir, no imprimirá el "console.log (" más código .. "), en cambio si ponemos" await "esperará cada función que se complete y finalmente siga la secuencia normal del código principal.
debajo de "console.log (" terminado 1 "elimina el" retorno ", verás el comportamiento.
fuente
Aquí hay un ejemplo mecanografiado que puede ejecutar y convencerse de que necesita ese "retorno en espera"
fuente
Diferencia notable: el rechazo de promesas se maneja en diferentes lugares
return somePromisepasará somePromise al sitio de la llamada yawaitsomePromise para asentarse en el sitio de la llamada (si hay alguno). Por lo tanto, si se rechaza somePromise, no será manejado por el bloque de captura local, sino por el bloque de captura del sitio de llamada.return await somePromisePrimero esperará alguna promesa de establecerse localmente. Por lo tanto, el valor o la excepción primero se manejarán localmente. => El bloque de captura local se ejecutará sisomePromisese rechaza.Razón:
return await Promiseespera tanto localmente como afuera,return Promiseespera solo afueraPasos detallados:
promesa de devolución
delay1Second();delay1Second(), la funcióndelay(1000)devuelve una promesa inmediatamente con[[PromiseStatus]]: 'pending. Vamos a llamarlodelayPromise.Promise.resolve()( Fuente ). Comodelay1Secondes una función asíncrona, tenemos:Promise.resolve(delayPromise)regresadelayPromisesin hacer nada porque la entrada ya es una promesa (ver MDN Promise.resolve ):awaitespera hasta quedelayPromisese resuelva.delayPromisese cumple con PromiseValue = 1:delayPromisees rechazado:regreso a la espera de la promesa
delay1Second();delay1Second(), la funcióndelay(1000)devuelve una promesa inmediatamente con[[PromiseStatus]]: 'pending. Vamos a llamarlodelayPromise.delayPromisese establezca.delayPromisese cumple con PromiseValue = 1:delayPromisese rechaza:Glosario:
Promise.[[PromiseStatus]]cambios dependingaresolvedorejectedfuente