JavaScriptのPromiseについて復習のためにまとめてみる
今回はそこそこ使うものの曖昧な理解でいたJavaScriptのPromiseについてまとめてみます。
まず例として下のような処理を考えてみます。
例
const func1 = () => setTimeout(() => console.log('func1'),1000);
const func2 = () => setTimeout(() => console.log('func2'),500);
const func3 = () => setTimeout(() => console.log('func3'),1000);
const func4 = () => setTimeout(() => console.log('func4'),500);
func1();
func2();
func3();
func4();
まずブラウザのコンソールで実行してみます。期待する処理としては 1秒後にfunc1が出力、その0.5秒後 func2が出力、その1秒後にfunc3が出力、そしてその0.5秒後ににfunc4が出力されるというもの
結果①
しかし実際には下記のような結果となりました。。(func2,func4,func1,func3の順に出力)
理由としてはsetTimeout関数の非同期処理(ある処理の実行の終了を待たず処理を実行する)の性質のためです。
これを解消するために下記のようなコードに書き換えてみます。
const funcAll = () => setTimeout(() => {
console.log('func
setTimeout(() =>
console.log('func2');
setTimeout(() => {
console.log('func3');
setTimeout(() => {
console.log('func4');
},500)
},1000)
},500)
},1000);
funcAll();
結果②
結果は下記のようになりました。
意図した通りに動くようにはなったものの、callback関数のネスト構造によって大変読みにくいコードになってしまっています。
これを解消するためにPromiseで上記のコードを書き換えてみます。(今度は表示されるのにかかった秒数も出力してみます)
const customFunc = (num,delaySecond,countSecond) => {
return new Promise ((resolve, reject) => {
setTimeout(() => {
console.log('func' + num + ' : ' + (countSecond + delaySecond) + 'ms');
resolve(countSecond + delaySecond);
}, delaySecond);
});
}
Promise.resolve()
.then(() => customFunc(1,1000,0))
.then((totalSecond) => customFunc(2,500,totalSecond))
.then((totalSecond) => customFunc(3,1000,totalSecond))
.then((totalSecond) => customFunc(4,500,totalSecond))
.finally(() => {
console.log('completed!!');
})
最終結果
実行結果がこちら
期待通りの処理になりました。コールバック関数のネスト構造も解消されています。
以下要点だけ解説
Promiseで非同期処理が正常に実行されるとresolveが実行されます。resolveの引数に渡された変数(上のコードの例だとcountSecond + delaySecond の部分)はメソッドチェーンになっている場合はthenの引数(上の場合だとtotalSecondの部分)に入ります。最後に実行したい処理がある場合はメソッドチェーンの最後でfinallyを使って処理を実行できます。
ちょっと説明不足感はありますが、今日はここまでにしておきます。
次は async,awaitなども含めてもう少し掘り下げた記事を書く予定です(もっと勉強します。。)