jsで非同期処理
以前、Vueでfirebaseのrealtime databaseとか、自分でNodeのAPI作って、フロントから叩く時に非同期処理でつまずいた経験があったので、まとめておきます。
非同期処理とは
非同期処理は、あるタスクが実行をしている際に、他のタスクが別の処理を実行できる方式である。
同期処理では、あるタスクが実行している間、他のタスクの処理は中断される方式である。
この仕組みのおかげで、並列に処理が走ることで描画が高速化したり、時間を無駄なく使えるって感じですね。
しかし、時には変数に値がない状態で、その変数を参照する処理が走ってしまってnullになっていたりと、厄介な問題も付きまといます。
そんな時に、便利なのがjsでよく使う async/awaitです(最近はPythonにもあるらしい)。
async/awaitの前に
ES6以前はcallback地獄というものがあったそうな。
そのおかげでネストが異常に深くなって、 ヒイィィィ!!!!(゚ロ゚ノ)ノ!という状態だったそうです。
そこで、Promiseというオブジェクトを使って処理するようになりました。
これにより、ネストは浅くなったのですが、.thenの大量発生、外の変数に退避しないと直前の結果を参照できないなど、課題がいろいろありました。
そこで、満を持してES8からasync/awaitが登場したという歴史的な背景があります。
厳密に理解をするにはPromiseの内容も合わせて理解しておくと良いと解説されている方もいるので、
興味のある方は合わせて見てみるといいかもしれないですね。
async/awaitの使い方
使い所としては、基本的にAPI叩く時とかが多い気がしています。
・関数の頭にasyncをつける
・処理が終わるまで待ってて欲しいところにawaitをつける
シンプルですね!
async function test() {
const item = {a:b, c:d}
// 何か非同期処理になるやつ
const result = await Api().post('/verify', item)
console.log(result)
}
ちなみにですが、以下のようにたくさんのawaitを使うと、非同期の良さを殺してる気がしてもったいない感じがしますよね。
async function many_await() {
var aaa = await Api().post('/aaa', 'aaa')
var bbb = await Api().post('/bbb', 'bbb')
var ccc = await Api().post('/ccc', 'ccc')
var ddd = await Api().post('/ddd', 'ddd')
var eee = [aaa, bbb, ccc, ddd]
}
こんな時は
以下のように、Promise.allとawaitの合わせ技でも使えるそうなので(今回調べて初めて知った)
使いこなせるといいですね!
async function many_await() {
var aaa = Api().post('/aaa', 'aaa')
var bbb = Api().post('/bbb', 'bbb')
var ccc = Api().post('/ccc', 'ccc')
var ddd = Api().post('/ddd', 'ddd')
var eee = await Promise.all([aaa, bbb, ccc, ddd])
}