Aguardando por mais de um concorrente aguardando operação

Como posso alterar o código a seguir para que as duas operações assíncronas sejam acionadas e tenham a oportunidade de serem executadas simultaneamente?

const value1 = await getValue1Async(); const value2 = await getValue2Async(); // use both values 

Eu preciso fazer algo assim?

 const p1 = getValue1Async(); const p2 = getValue2Async(); const value1 = await p1; const value2 = await p2; // use both values 

TL; DR

Não use o padrão na pergunta onde você recebe as promises, e então espere separadamente; em vez disso, use Promise.all (pelo menos por enquanto):

 const [value1, value2] = await Promise.all([getValue1Async(), getValue2Async()]); 

Embora a sua solução execute as duas operações em paralelo, ela não controla a rejeição corretamente se ambas as promises forem rejeitadas.

Detalhes:

Sua solução os executa em paralelo, mas sempre espera que o primeiro termine antes de aguardar o segundo. Se você quiser apenas iniciá-los, executá-los em paralelo e obter os dois resultados, tudo bem. (Não, não é, continue lendo …) Observe que, se o primeiro levar (digamos) cinco segundos para ser concluído e o segundo falhar em um segundo, seu código aguardará cinco segundos antes de falhar.

Infelizmente, não há atualmente uma syntax para fazer uma espera paralela, então você tem o constrangimento que você listou, ou Promise.all . (Houve discussão de await.all ou algo semelhante , talvez; talvez algum dia).

A versão Promise.all é:

 const [value1, value2] = await Promise.all([getValue1Async(), getValue2Async()]); 

… que é mais conciso, e também não espera que a primeira operação seja concluída se a segunda falhar rapidamente (por exemplo, no meu exemplo de cinco segundos / um segundo acima, o acima será rejeitado em um segundo em vez de esperar cinco) . Observe também que, com o código original, se a segunda promise for rejeitada antes da primeira promise ser resolvida, você poderá receber um erro de “rejeição não tratada” no console (você usa o Chrome v61), embora esse erro seja possivelmente falso fazer , eventualmente, lidar com a rejeição). Mas se ambas as promises forem rejeitadas, você receberá um erro de rejeição genuíno e não manipulado, porque o stream de controle nunca atinge valor const value2 = await p2; e, portanto, a rejeição p2 nunca é tratada.

Rejeições não tratadas são uma coisa ruim (tanto que, em breve, o NodeJS abortará o processo em rejeições verdadeiramente não tratadas, assim como exceções não tratadas – porque é isso que elas são), então é melhor evitar o padrão “obter a promise, então await ” na sua pergunta.

Aqui está um exemplo da diferença de tempo no caso de falha (usando 500ms e 100ms em vez de 5 segundos e 1 segundo), e possivelmente também o erro de rejeição sem manipulação (abra o console real do navegador para vê-lo):

 const getValue1Async = () => { return new Promise(resolve => { setTimeout(resolve, 500, "value1"); }); }; const getValue2Async = () => { return new Promise((resolve, reject) => { setTimeout(reject, 100, "error"); }); }; // This waits the full 500ms before failing, because it waits // on p1, then on p2 (async () => { try { console.time("separate"); const p1 = getValue1Async(); const p2 = getValue2Async(); const value1 = await p1; const value2 = await p2; } catch (e) { console.error(e); } console.timeEnd("separate"); })(); // This fails after just 100ms, because it doesn't wait for p1 // to finish first, it rejects as soon as p2 rejects setTimeout(async () => { try { console.time("Promise.all"); const [value1, value2] = await Promise.all([getValue1Async(), getValue2Async()]); } catch (e) { console.timeEnd("Promise.all", e); } }, 1000); 
 Open the real browser console to see the unhandled rejection error. 

Eu acho que isso deve funcionar:

  const [value1, value2] = await Promise.all([getValue1Async(),getValue2Async()]);