O MDN diz que for await...of
tem dois casos de uso:
A
for await...of
instrução cria um loop que itera sobre objetos iteráveis assíncronos, bem como sobre iteráveis de sincronização, ...
Eu já tinha conhecimento do primeiro: async iterables usando Symbol.asyncIterator
. Mas agora estou interessado no último: iterables síncronos.
O código a seguir itera sobre uma iterável síncrona - uma matriz de promessas. Parece bloquear o progresso no cumprimento de cada promessa.
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)
O comportamento parece ser semelhante a aguardar cada promessa por sua vez, de acordo com a lógica mostrada abaixo. Esta afirmação está correta?
Eu pergunto porque esse padrão de código tem uma armadilha fio-up rejeição implícita de que Promise.all
e Promise.allSettled
evitar, e parece estranho para mim que esse padrão seria explicitamente suportada pelo idioma.
fonte
for await... of
iterables síncronos está correta e, em caso afirmativo, importa que esse padrão possa emitir erros de rejeição sem tratamento?Respostas:
Sim, é estranho, e você não deve fazer isso. Não itere séries de promessas, pois isso leva exatamente ao problema de rejeições não tratadas que você mencionou .
Então, por que isso é suportado no idioma? Para continuar com a semântica da promessa desleixada.
Você pode encontrar o raciocínio exato neste comentário da questão que discute esta parte da proposta :
fonte
unhandledrejection
eventos?window.addEventListener('unhandledrejection',...
Em resumo: é o único exemplo que posso lembrar desse tipo de emissão de erro por JavaScript. Estou quase certamente errado em pensar isso, no entanto. Finalmente: a emissão desse "erro" realmente importa além de ter uma mensagem de erro indesejada no console?A
sad
promessa não está sendo cumpridaawait
quando falha - esse código precisa terminar a esperahappy
antes que possa começar a esperarsad
. Asad
promessa está falhando antes dehappy
resolver. (Promise.all
é uma ferramenta mais adequada para este caso de uso)fonte
Promise.all
é uma solução melhor, por que o idioma atende a essa sintaxe?for await...of
poderia facilmente ter sido implementado para simplesmente enumerar iterables assíncronos. Mas eles serviram para enumerar iteráveis síncronos (mas com uma (aparentemente?) Armadilha). Por quê?for await ... of
aceita iterables síncronos? Eu imaginaria suportar geradores assíncronos que condicionalmente podem retornar itens síncronos.