自分用のメモ。
呼び出される順
const a = new Promise(function (resolve, reject) { console.log("a"); }); const b = new Promise(function (resolve, reject) { console.log("b"); }); const c = new Promise(function (resolve, reject) { console.log("c"); }); Promise.all([a, b, c]).then(function (value) { console.log(value); //呼ばれない }); ------出力結果------- a b c
a
が1番目、b
が2番目、c
が3番目に呼ばれる。- ただし、
a,b,c
ともに全て非同期処理なので、a
が1番目に終わるとは限らない。(この場合はどれも軽い処理なので絶対にaが1番に終わる) resolve
は呼ばれていないので、Promise.all
のコールバックも呼ばれない。
コールバックの引数の順番
すべてresolve
const a = new Promise((resolve, reject) => { console.log("a"); setTimeout(resolve, 3000, "aが終わった"); }); const b = new Promise((resolve, reject) => { console.log("b"); setTimeout(resolve, 2000, "bが終わった"); }); const c = new Promise((resolve, reject) => { console.log("c"); setTimeout(resolve, 1000, "cが終わった"); }); Promise.all([a, b, c]).then((values) => { console.log(values); //呼ばれる }); ------出力結果------- a b c ["aが終わった","bが終わった","cが終わった"]
a,b,c
の全てでresolve
が呼ばれているので、Promise.all
のコールバックも呼ばれる。- コールバックに入ってくる
resolve
の引数は、呼び出した順になる。
(この場合、一番最初に処理が終わるのはc
だが、["cが終わった","bが終わった","aが終わった"]
という順番にはならずに、a→b→cという呼び出し順である["aが終わった","bが終わった","cが終わった"]
になる)
1つだけreject
const a = new Promise((resolve, reject) => { console.log("a"); setTimeout(resolve, 3000, "aが終わった"); }); const b = new Promise((resolve, reject) => { console.log("b"); setTimeout(reject, 2000, "bが終わった"); }); const c = new Promise((resolve, reject) => { console.log("c"); setTimeout(resolve, 1000, "cが終わった"); }); Promise.all([a, b, c]) .then((values) => { console.log(values); //呼ばれない }) .catch((err) => { console.log(err); //呼ばれる });
Promise.all
は「渡したすべてのPromiseがreloveされたらコールバックを実行する」という関数なので、この場合はbでrejectを呼んでいるので、コールバックは呼ばれない。その代わりにcatch文の部分が呼ばれる。- また、
Promise.all
は「渡した全てのpromiseがresolveされるまで待つけど、どれか1つでもrejectされたらrejectする」という性質もある。- なので「aはresolveされたけど、b,cは実行中」という場合に、bがrejectされた場合は、cの処理を途中でストップする
- 逆に「結果に関わらず、a,b,cのすべてを最後まで実行したい!」という場合は、
Promise.allSettled
を使う。
おわり
関連:Promise.allSettled、Promise.all、Promise.any、Promise.raceの違い
コメント