MDN dice que for await...of
tiene dos casos de uso:
La
for await...of
instrucción crea un ciclo que itera sobre objetos iterables asíncronos, así como en iterables sincronizados, ...
Anteriormente estaba al tanto de lo anterior: los iterables asíncronos usando Symbol.asyncIterator
. Pero ahora estoy interesado en lo último: iterables sincrónicos.
El siguiente código itera sobre un iterable síncrono: una serie de promesas. Parece bloquear el progreso en el cumplimiento de cada promesa.
async function asyncFunction() {
try {
const happy = new Promise((resolve)=>setTimeout(()=>resolve('happy'), 1000))
const sad = new Promise((_,reject)=>setTimeout(()=>reject('sad')))
const promises = [happy, sad]
for await(const item of promises) {
console.log(item)
}
} catch (err) {
console.log(`an error occurred:`, err)
}
}
asyncFunction() // "happy, an error occurred: sad" (printed in quick succession, after about 5 seconds)
El comportamiento parece ser similar a esperar cada promesa por turno, según la lógica que se muestra a continuación. ¿Es correcta esta afirmación?
Pregunto porque este patrón de código tiene un error implícito de rechazo de conexión Promise.all
y Promise.allSettled
evitarlo, y me parece extraño que este patrón sea respaldado explícitamente por el lenguaje.
fuente
for await... of
correcta mi descripción de iterables sincrónicos? De ser así, ¿importa que ese patrón pueda emitir errores de rechazo no controlados?Respuestas:
Sí, es extraño, y no debes hacer esto. No repita los arreglos de promesas, esto conduce exactamente al problema de rechazos no controlados que mencionó .
Entonces, ¿por qué se admite esto en el idioma? Para continuar con la promesa descuidada semántica.
Puede encontrar el razonamiento exacto en este comentario del tema que discute esta parte de la propuesta :
fuente
unhandledrejection
eventos?window.addEventListener('unhandledrejection',...
En resumen: es la única instancia que puedo recordar, de este tipo de emisión de error por JavaScript. Sin embargo, es casi seguro que me equivoco al pensar esto. Finalmente: ¿la emisión de este "error" realmente importa más allá de tener un mensaje de error no deseado en la consola?La
sad
promesa no está siendoawait
ed cuando falla - que las necesidades de código para terminar la espera dehappy
que pueda comenzar a esperar ensad
. Lasad
promesa está fallando antes dehappy
resolverse. (Promise.all
es una herramienta más adecuada para este caso de uso)fuente
Promise.all
es una mejor solución, ¿por qué el lenguaje atiende esta sintaxis?for await...of
podría haberse implementado fácilmente para enumerar simplemente iterables asincrónicos. Pero se encargaron de que enumerara iterables sincrónicos (pero con una trampa (¿aparente?)). ¿Por qué?for await ... of
acepta iterables sincrónicos? Me imagino que admite generadores asíncronos que condicionalmente pueden devolver elementos sincrónicos.