はじめに
JSを学習するにあたり、非同期処理(Promise、async、await等)について理解ができてないので簡単にまとめてみました。
「そもそも非同期処理って何??」って、最初は疑問をもつと思います。
なので、まずは概念的な部分からさぐっていき、JSの非同期処理の定番であるPromise、async、awaitについてまとめていきます。
概念(同期処理、非同期処理)
同期処理はプログラムを上から順に処理していくこと。ひとつの処理が完了するまで次の処理は行われません。
非同期処理は同期処理とは違って、ひとつの処理を行っている間、別の処理を並行して行えます。
その2つの違いをわかりやすく日常的なことを取り入れて、図解にすると下の違いです。
同期処理 非同期処理
掃除 Netflixみる 掃除 Netflixみる
| |
| |
|ーーーーーー| |ーーーーーー|
中断 | 継続| |
| | |
|ーーーーーー| |ーーーーーー|
| |
| |
このようにみると、日常が非同期処理だと楽ですよね。同期処理とは違って、実行完了を待たずに処理を実行しています。
改めてJSが言う非同期処理とは
・Web API(通信が発生する処理)
・データベース通信
・実行完了を待たない
などの以上のことが可能です。
コードで簡単に記述していくと、
//非同期処理
console.log(1)
setTimeout(function() {
console.log(2)
},1000) //1秒後出力
console.log(3)
// 結果
1
3
2
と3の数字が先にきていることがわかります。
非同期通信メソッドである、fetchを利用していく例だと、、
const fetchFunc = () => {
const url = '外部API(https://..........)'
// APIへの非同期処理
fetch(url).then(response => {
console.log("非同期処理が完了しました!")
return '完了'
})
.catch(() => {
console.error('非同期処理が失敗です。')
return '失敗!'
})
}
const message = '非同期処理'
const result = fetchFunc()
console.log(message + result)
// 結果
非同期処理undefined
非同期処理が完了しました!
fetchFuncの結果がundefinedになり、messageとresultを返した値が出ています。
また、fetchメソッドは、urlが取得した値をresponseで呼び出します。
良い面😆
ユーザーを待たせない(外部との通信に時間がかかる間に、ユーザーは別のことに取り掛かりたい)ということが挙げられますが、
悪い面😱
実行完了までにデータが存在しないということです。
例えば、Web APIを叩いた際に、レスポンスがまだ帰ってきてない時に実行完了すると、Web APIのデータが存在せず、レスポンスを待たずにタスクが完了してしまう。
上の例でいくと、APIの非同期処理が後から出力されていることがわかりますね。
その非同期処理を待つ方法としてあげられるのが、Promiseとasync,awaitです。
Promise
非同期処理の状態を表すオブジェクト
ちなみに日本語だと「約束」Promise
具体的にいうと、実行完了を待って値を渡してから、次の処理に移ります。
そして、Promiseの状態を表すのが、
・pending:非同期処理の実行中の状態
・fulfilled:処理が成功した状態 =(resolve()メソッド)
・rejected:処理が失敗した状態 =(rejected()メソッド)
を表します。
非同期関数を書き換えてみると、、
// Promise
const promiseFunc = () => {
return new Promise((resolve,reject) => {
const url = '外部API(https://..........)'
fetch(url).then(() => {
console.log('このPromiseは完了しました!')
return resolve('完了')
}).catch(() => {
console.log('このPromiseは失敗しました!')
return reject
})
})
}
const message2 = 'Promise'
// 非同期処理を実行してthenでチェインする
promiseFunc().then(result => {
// resultは引数で、returnした値が帰ってくる(resolve)
console.log(message2 + result)
})
// 結果
このPromiseは完了しました!
Promise完了
return new Promise((resolve,reject) => {}と記述することでPromiseができます。
コード中にも記述してありますが、関数名.then(引数 => {})でチェインして、引数(実行結果)の値を取得します。
async,await
Promiseよりもわかりやすい記述で、直感的にわかりやすい。
日本語だと、「非同期」async、「待つ」awaitです。
それぞれの役割としては、
・async 非同期処理の関数定義につける
・await 〃 の実行関数につける
・また、awaitはasyncの関数内でしか使えない
と行った具合になります。
// async await
const asyncFunc = async() => {
const message3 = 'async await'
const url = '外部API(https://..........)'
const hoge = await fetch(url).then(() => {
console.log('このasync,awaitは完了しました!')
return '完了'
}).catch(() => {
console.log('このasync,awaitは失敗しました!')
return '失敗'
})
console.log(message3 + hoge)
return
}
asyncFunc()
// 結果
このasync,awaitは完了しました!
async await完了
async関数内で定義したことにより、fetchメソッドの前にあるawaitが働くことによって、hogeという関数の処理が終わった後に、console.logが出力されますね。
感想
Web APIを操作することを今後、やっていくとなると必ずぶち当たると思うので、要約してみました。async,awaitを少し触った程度の内容ですので、例外処理についてもアウトプットしていきたいです。
参考にさせていただいたサイト
https://tech.playground.style/javascript/asynchronous-processing/