また自分の理解したことのメモです。
JavaScriptの非同期処理に関して、主にPromiseとasync/awaitについて理解したことをまとめたいと思います。
非同期処理
同期処理とは、簡単に説明すると処理が上から順番に行われていくことです。
console.log(1);
console.log(2);
console.log(3);
1
2
3
これに対し、非同期処理とは1つの処理が終わるのを待たずに次の処理が行われることです。例として非同期関数であるsetTimeout()を使用してみます。
console.log(1);
setTimeout(function(){
console.log(2)
},100);
console.log(3);
1
3
2
このようにsetTimeout()の処理を待たずにあとの処理が先に行われました。これはサーバーとの通信などで時間のかかる処理によって、プログラム全体が止まってしまわないようにするために使われます。
Promise
Promiseとは非同期処理の状態を表すオブジェクトです。Promiseには以下の3つの状態があります。
・pending : 処理が実行中
・fulfilled : 処理が成功
・rejected : 処理が失敗
Promiseの処理が終了した後に、結果を利用するにはPromiseのメソッドであるthen()とcatch()を用います。
・then() : Promiseの状態がfulfilledのとき実行される処理
・catch() : Promiseの状態がrejectedのとき実行される処理
以下のような例で具体的に説明します。
//Promiseオブジェクトを返す関数を定義
function time(sec){
return new Promise(function(resolve,reject){
setTimeout(function(){
//100より小さいと成功(fulfilledの状態を返す)
if(sec <= 100){
resolve();
}
//それ以上では失敗(rejectedの状態を返す)
else{
reject();
}
},sec)
})
};
console.log(1);
time(100)
.then(function(){console.log('success')})
.catch(function(){console.log('error')})
time(1000)
.then(function(){console.log('success')})
.catch(function(){console.log('error')})
console.log(2);
1
2
success
error
Promiseオブジェクトを返す関数として戻り値がnew Promiseとなる関数を定義します。resolve(),reject()はそれぞれ処理が完了した時、失敗したときに呼び出されます。time(100)のときはPromiseの状態がfulfilledで返されるため、then()の中の処理が行われ、一方、time(1000)のときはPromiseの状態がrejectedで返されるため、catch()の中の処理が行われます。
また、then()メソッドは戻り値としてPromiseオブジェクトを返すため、連続して書くことができます。この時途中でエラーが起きると処理が飛ばされcatch()が呼び出されます。
time(100)
.then(function(){console.log(1)})
.then(function(){console.log(2)})
.then(function(){console.log(3)})
.catch(function(){console.log('error')})
console.log(4)
4
1
2
3
async/await
async/awaitを用いた非同期処理の構文について説明します。asyncとは関数の前に宣言することで、非同期関数を定義することができます。
//非同期関数の宣言
async function sample() {}
非同期関数は戻り値として、Promiseオブジェクトを返します。関数の処理が実行され、値を返すと戻り値をresolveが呼び出され、何らかのエラーなどが起こるとrejectが呼び出されます。
asyncで定義した非同期関数の中ではawaitという演算子が使用できます。awaitを関数の前に指定すると、その関数のPromiseオブジェクトが結果を返すまでその後の処理が待機します。
//awaitを用いない時
async function sample1(){
time(100)
.then(function(){console.log(1)})
console.log(2);
}
//awaitを用いた時
async function sample2(){
await time(100)
.then(function(){console.log(1)})
console.log(2);
}
sample1();
sample2();
2
1
1
2
awaitを用いない場合、関数の中の非同期処理より先にあとの処理が実行されますが、awaitを用いると指定した関数の処理が終了するまであとの処理が行われません。
非同期処理を同期的に処理したい場合、Promiseのthen()メソッドを用いるよりも、async/awaitを用いるほうが簡潔な記述でかけることが多いです。
まとめ
JavaScriptの非同期処理に関することとして、Promiseとasync/awaitについてまとめてみました。async/awaitを用いると記述が簡潔になりますが、新しい規格のため対応していないこともあるので注意が必要です。
参考記事
[【JavaScript】Promise で非同期処理を記述するー株式会社ライトコードー]
(https://rightcode.co.jp/blog/information-technology/javascript-promise)
JavaScriptと非同期処理の話
[async/await 入門(JavaScript)]
(https://qiita.com/soarflat/items/1a9613e023200bbebcb3#resolve%E3%81%99%E3%82%8B)