Si llama a una función asíncrona desde un código no asíncrono, cualquier cosa después de la espera se ejecuta de forma asíncrona con respecto a la persona que llama:
async function asyncInner() { console.log('before asyncInner'); await Promise.resolve() console.log('after asyncInner'); } console.log('start'); asyncInner() console.log('end');En otras palabras, esto imprime:
start before asyncInner end after asyncInnerPero si llama a esta función asíncrona desde otra función asíncrona :
async function asyncInner() { console.log('before asyncInner'); await Promise.resolve() console.log('after asyncInner'); } async function asyncOuter() { console.log('before asyncOuter'); await asyncInner(); console.log('after asyncOuter'); } console.log('start'); asyncOuter() console.log('end');usted obtiene:
start before asyncOuter before asyncInner end after asyncInner after asyncOuter En otras palabras, el método interno se completa sincrónicamente con respecto al método externo. ¿Por qué es esto y cómo podría escribirse para que asyncOuter se complete antes que asyncInner ?
(Sé que podría usar un setTimeout para esto, pero prefiero evitar el uso de devoluciones de llamada, porque una de las cosas buenas de async es evitar el infierno de devolución de llamada).
En otras palabras, el método interno se completa sincrónicamente con respecto al método externo. ¿Por qué es esto y cómo podría escribirse para que asyncOuter se complete antes que asyncInner?
En realidad, no es sincrónico, pero tiene razón en que esperará a que finalice la función interna antes de continuar con la función externa. La razón por la que esperará es porque le dijiste que esperara con la palabra clave await . Si no quieres que espere, simplemente déjalo fuera.
async function asyncInner() { console.log('before asyncInner'); await Promise.resolve() console.log('after asyncInner'); } async function asyncOuter() { console.log('before asyncOuter'); asyncInner(); // <--------- removed the await console.log('after asyncOuter'); } console.log('start'); asyncOuter() console.log('end');@Keith: Veo que estaba confundiendo "sincrónico" con "esperado".
Incluso entonces es un poco vago. await en Javascript es realmente un azúcar de sintaxis elegante para promise.then(result => {}) Así que nada realmente espera, es solo que el infierno de devolución de llamada se convierte en algo que parece sincrónico y, como tal, mucho más fácil de razonar.
Podría tener más sentido si eliminamos await y lo hacemos a la antigua usanza de thenable .
Entonces, a continuación, convertí su ejemplo para que se ejecute sin await y, como puede ver, da el mismo resultado, pero esta vez estamos usando la devolución de llamada. Entonces, si comprende las devoluciones de llamada, entonces tiene más sentido por qué obtiene el resultado que obtiene.
function asyncInner() { console.log('before asyncInner'); return Promise.resolve().then(r => console.log('after asyncInner')); } function asyncOuter() { console.log('before asyncOuter'); return asyncInner().then(() => console.log('after asyncOuter')); } console.log('start'); asyncOuter() console.log('end');