1. ホーム
  2. javascript

[解決済み] async/await関数を並列に呼び出す

2022-03-14 02:04:13

質問

私の理解する限り、ES7/ES2016では、複数の await を連鎖させるのと同じように動作します。 .then() はプロミスで、つまり、並列ではなく、1つずつ実行されます。例えば、こんなコードです。

await someCall();
await anotherCall();

というのは正しい理解でしょうか? anotherCall() が呼び出されるのは someCall() が完了したら?それらを並列に呼び出す最もエレガントな方法は何でしょうか?

Nodeで使いたいので、asyncライブラリで解決できるかも?

EDIT: 私はこの質問で提供された解決策に満足していません。 非同期ジェネレータにおけるプロミスの非並列待ちによる速度低下 なぜなら、それはジェネレーターを使用しており、私はより一般的な使用例について質問しているからです。

解決方法は?

で待機させることができます。 Promise.all() :

await Promise.all([someCall(), anotherCall()]);

結果を保存するため。

let [someResult, anotherResult] = await Promise.all([someCall(), anotherCall()]);

なお Promise.all は高速に失敗します。つまり、それに供給された約束の1つが拒否されるとすぐに、それ全体が拒否されるのです。

const happy = (v, ms) => new Promise((resolve) => setTimeout(() => resolve(v), ms))
const sad = (v, ms) => new Promise((_, reject) => setTimeout(() => reject(v), ms))

Promise.all([happy('happy', 100), sad('sad', 50)])
  .then(console.log).catch(console.log) // 'sad'

その代わりに、すべての約束が果たされるか拒否されるのを待ちたい場合は Promise.allSettled . ただし、Internet Explorerはこの方式をネイティブにサポートしていません。

const happy = (v, ms) => new Promise((resolve) => setTimeout(() => resolve(v), ms))
const sad = (v, ms) => new Promise((_, reject) => setTimeout(() => reject(v), ms))

Promise.allSettled([happy('happy', 100), sad('sad', 50)])
  .then(console.log) // [{ "status":"fulfilled", "value":"happy" }, { "status":"rejected", "reason":"sad" }]

を使用する場合 Promise.all 拒絶が起こる前に終了することができたアクションはロールバックされないので、そのような状況に対処する必要があるかもしれません。例えば 5つのアクションがあり、4つがクイック、1つがスロー、そしてスローがリジェクトされたとします。この4つの はすでに実行されている可能性があるので、ロールバックが必要な場合があります。そのような場合は Promise.allSettled どのアクションが失敗し、どのアクションが失敗しなかったかを正確に教えてくれるからです。