Promiseを定義したときにasync/awaitするとコードを見たまま上から下に実行されるので難しくないのですが、then/catchで後の処理を定義するとどのタイミングでコールバックが実行されるのかわかっていませんでした。
ちょっと調べてみたのでまとめます。
サンプル
aとbというPromiseを作ってそれぞれの関数の中でログを出力してみます。
また、各定義の間と、aとbをPromise.allした後にもログを出力します。
const a = new Promise((resolve, reject) => {
console.log('a');
resolve('a: resolve');
})
.then(() => { console.log('a: then'); });
console.log('aの後')
const b = new Promise((resolve, reject) => {
console.log('b');
resolve('b: resolve');
})
.then(() => { console.log('b: then'); });
console.log('bの後')
Promise.all([a, b])
.then(() => { console.log('c: then'); });
console.log('d');
結果は次のようになりました。
[LOG]: "a"
[LOG]: "aの後"
[LOG]: "b"
[LOG]: "bの後"
[LOG]: "d"
[LOG]: "a: then"
[LOG]: "b: then"
[LOG]: "c: then"
ふむ、thenの中の出力は定義後のdの後に表示されました。
どうしてこうなった
書き慣れてる人はこんな挙動は当然よく見てて知ってると思うのですが、どういう仕様なんでしょう?
これらのページを読んでたら下のように定義されていました。
保証
旧来のコールバック渡しとは異なり、プロミスでは以下のことが保証されています。
- then() によって追加されたコールバックは、現在の JavaScript イベントループの現在の処理の完了より前には決して呼び出されません。
サンプルに書いたような状況だとdを出力する箇所が完了してからすべてのthenが処理されるという感じですかね。
async/awaitとthen/catchをなんとなくで書き分けないで状況によって書き分けられるようになりたいですねー。