JavaScript ES6のAsync/Awaitで非同期処理とエラー処理、並列処理を解説!初心者向け完全ガイド
この記事では、ES6のasync/await、およびPromises.all()を使用して非同期プログラミングを容易にする方法を学習します。
前回でのPromiseチュートリアルは以下で学ぶことができますので参照ください。
async/awaitとは
async/awaitは技術的に言えば、Promisesのシンタックスシュガー(Syntax sugar)となります。
シンタックスシュガーとは簡単に言ってしまえば、構文を省略しプログラムを書いていく事をシンタックスシュガーと言います。
ですが、これはプログラミング言語によって異なってきますのでご注意下さい。
現代の非同期JavaScriptはかつてないほど簡単になりました。
JavaScriptは、コールバックからプロミス(ES2015)まで、すさまじい速さで進化しました。
また、ES2017以降、非同期JavaScriptは、async/await構文を使用することで同期コードのように見えるが、読みやすい非同期コードを記述でにるようになり、さらにシンプルになりました。
つまり、遥かむかしではコールバックを使用し、次にPromiseを使用し始め、現在はこれからあなたが学ぶasync/await構文となります。
よくある誤解は、async/awaitとPromiseは完全に異なるものであると思っている方です、決してそんな事はありません。
async/awaitはPromiseに基づいて構築されます。
これはasync/awaitはPromiseの拡張された構文でもあるという事になります。
async関数を使用すると、非同期JavaScriptを簡単に作成できますが、初心者にとっては困難でありまた独自の落とし穴があります。
最後に解説しますが、使用する際の注意点も抑えておいて下さい。
それでは、async/awaitの世界へ
asyncキーワード
まずはasyncキーワードから学んでいきましょう。
asyncは関数の前に配置させます。
これは構文で決まりになっていますので必ず、関数の前に記述して下さい。
通常の関数宣言で使用可能です。
async function functionName() { return 1; }
アロー関数の機能でも使用できます。
const functionName = async (x) => { }
つまりこれは、無名関数でも使用可能という意味にもなります。
これによってJavaScriptは、async/await構文を使用していることを認識できます。
asyncキーワードが配置された関数は常にPromiseを返すようになります。
つまり、あなたが何をしているのかは関係ありません戻り値は常にPromiseとなります。
const x = async () => { return 1 } const result = x() console.log(result) // Promise
では上記の関数を、1の結果で解決されたPromiseを返しアラートで通知させてみましょう。
const result = async () => 1; return().then(alert); // 1
値は、解決されたPromiseに自動的にラップされます。
See the Pen JSのPromiseのasync by dev.K | Webアプリ開発者 (@enjinia_f) on CodePen.
これは次のような事とやっている事は同じになります。
const x = async () => { return Promise.resolve(1); } x().then(alert); // 1
明示的に書かなくとも、先述した通りに戻り値(return)は常にPromiseとなります。
したがって、async関数がPromiseを返し、Promise以外をラップするようにします。
難しい事はなく簡単ですね。
ですがそれだけではございません。
async関数内でのみ機能する別のキーワードがありasyncは以前のPromiseと比べ、かなりクールな機能となっています。
awaitキーワード
このawaitキーワードにより、JavaScriptはそのPromiseが解決済みまたは拒否された結果を返すまで待機します。
const x = await myPromise;
await演算子は、Promiseを待機するために使用されますが非同期ブロック内でのみ使用可能となります。
同期関数内ではawaitは使用できません。
そして、awaitで呼び出される側の関数にはPromiseオブジェクトを(resolve)返してあげて下さい。
// 呼び出される側の関数 function myPromise() { return new Promise((resolve, reject) => { //何かしらの処理 resolve(0) //返す }) }
// awaitを使用する側 const sampleAsync = async () => { const result = await myPromise() } //functionキーワード async function sampleAsync() { const result = await myPromise() }
・ awaitが呼び出される側はPromiseオブジェクトを返す。
・ Promiseオブジェクト内では、returnで返さないようにして下さい。
・ awaitを使用する側の関数にはasyncを関数の前に配置する。
これら上記の注意点が初心者様は、うまく動作してくれずに思い通りのコードが書けないという状況になります、これは意外な落とし穴となっておりますのでご注意下さい。
それでは実際にawaitを使用してみましょう。
下記では、2秒後に解決するPromiseとなります。
まずはasyncを関数の前に配置させ、常にPromiseとして機能させます。
setTimeout()で2秒指定にします。
const x = async () => { let myPromise = new Promise((resolve, reject) => { setTimeout(() => resolve("解決済み!"), 2000) }); let result = await myPromise; console.log(result); } x();
上記のコードは、非同期関数x
を定義しています。この関数は次のような動作をします。
非同期関数x
が呼び出されると、以下の処理が順番に実行されます。
1. x
関数内で新しい Promise オブジェクトmyPromise
が作成されます。このPromiseは、2秒後に解決(resolve)されるように設定されています。
2. その後、awaitキーワードを使ってmyPromise
の解決を待機します。await キーワードを使用すると、非同期処理が完了するまでスクリプトの実行が一時停止されます。
3. 2秒の待機時間が経過すると、myPromise
が解決され、その解決値が変数result
に代入されます。
4. 最後に、result
の値がconsole.logを使って出力されます。
したがって、上記のコードを実行すると、2秒の待機後に "解決済み!" という文字列がコンソールに表示されます。
このように、非同期関数内でPromiseを使用することで、非同期処理の完了を待機し、その結果を扱うことができます。await キーワードを使用することで、非同期処理をより直感的かつ同期的に扱うことができます。
つまりは、awaitの仕事はPromiseが解決するまで関数の実行を文字通り中断し、Promiseの結果で再開させます。
.then()
よりも、さらに洗練されたPromiseの結果を取得するための構文となります。
See the Pen JSのPromiseのawaitのdemo by dev.K | Webアプリ開発者 (@enjinia_f) on CodePen.
Async関数は常に待機する必要はありません
asyncで、awaitがなくても自由に使用しても構いません。
ですが、これはそれほどあまり一般的に広く使用されているわけではありませんが、Promiseで値をラップする必要がある際は非常に役に立ちます。
const sample = async () => { return "Hello" }
ですが前述したように、広く使用されていない為awaitの使用がない場合は、基本的にはasyncにこだわる必要はありません。
async関数では、複数のawaitキーワードを追加し待機が可能です。
まずは、以前での.then()
メソッドによる例と比較して見てみましょう。
const results = ms => { return new Promise(res => setTimeout(res, ms)) } const getResult1 = () => { return results(1000).then(x => 1) } const getResult2 = () => { return results(1000).then(x => 2) } const getResult3 = () => { return results(1000).then(x => 3) } const funAsync = async () => { const first = await getResult1() console.log(first) const second = await getResult2() console.log(second) const third = await getResult3() console.log(third) console.log('完了しました!') } funAsync()
上記ではsetTimeout()のミリ秒指定で1秒ずつthenによって順番に処理され、1・2・3で完了の通知をします。
See the Pen JSのasync/await 複数のawaitを待機 by dev.K | Webアプリ開発者 (@enjinia_f) on CodePen.
このコードでは、results
関数によって1秒待機する処理が3回行われ、その後に結果が表示されます。非同期処理の流れが直感的に理解できるように示しています。
しかし、async/await構文を使用している場合、.then()
メソッドを使う必要はありません。
async/await構文は、非同期処理をより直感的かつ同期的に扱うための機能です。await キーワードを使用することで、非同期関数の結果を直接待機し、その結果を変数に代入することができます。
したがって、上記のコードでは.then()
メソッドを使用する必要はありません。代わりに、次のようにコードを書くことができます
const funAsync = async () => { const first = await getResult1() console.log(first) const second = await getResult2() console.log(second) const third = await getResult3() console.log(third) console.log('完了しました!') } funAsync()
await キーワードを使用することで、getResult1()
の結果を待機し、その結果をfirst
変数に直接代入します。
同様に、getResult2()
の結果を待機し、second
変数に代入し、getResult3()
の結果を待機し、third
変数に代入します。
awaitキーワードを使用することで、非同期処理の結果を直接取得し、変数に格納できるため、.then()
メソッドを使用する必要はありません。
const funAsync = async () => { const first = await getResult1() console.log(first) const second = await getResult2() console.log(second) const third = await getResult3() console.log(third) console.log('完了しました!') }
上記のように、複数のawaitキーワードを追加して処理の待機ができますが、これは、必ずしも悪いということではありませんが、async/awaitは並列実行を行う方がはるかに高速な処理となっております。
なぜ複数の場合、並列を推奨されるのかを説明します。
awaitを複数回使用する場合、処理は直列的に実行されます。つまり、前の非同期処理が完了するまで次の非同期処理は待機します。このため、非同期処理が依存関係を持つ場合や、前の処理の結果を使って次の処理を行う必要がある場合には適しています。
ただし、複数の非同期処理が互いに依存しない場合や、処理の順序が重要でない場合、または並列で実行してパフォーマンスを向上させたい場合は、awaitを使用せずに非同期処理を並列実行する方法があります。これにより、複数の非同期処理が同時に実行され、それぞれの処理が終了するのを待つ必要がありません。
const result = async () => { await promise1(10); // 10秒… await promise2(30); //さらに30秒待つ return "完了!"; }
また、先述で学んできたような処理と上記での、この場合では大きなリクエストや重い処理は非常に時間がかかる可能性があるため、これは最善の良い方法とは言えません。
ですので実行を並列させる必要があります。
Promise並列処理
実行を並列処理するには、Promise.all()関数を実行する方法です。
つまり複数の待機(await)を並行して同時に実行します。
async/awaitによる非同期処理を、いくつかまとめて並列実行したい場合に使用します。
このpromise.all()関数は、イテレータ内(配列)のすべてのPromiseが解決されたときに解決され、その結果を返します。
反復可能なPromiseを入力として受け取り、入力Promiseの結果の配列に解決される単一を返します。
複数のasync関数を呼び出すと、それらがすべて解決され、出力が配列に保存されるまで待機することができます。
簡単な例を見てみましょう。
const promiseTime1 = (value, delay) => { return new Promise((resolve) => setTimeout(() => resolve(value), delay)); } const promiseTime2 = (index, delay) => { return new Promise((reject) => setTimeout(() => reject(index), delay)); } const promiseResult = async () => { const promiseAll = Promise.all([ promiseTime1(["banana", "tomato"], 1000), promiseTime2(["orange", "apple"], 1000) ]); // wait...(待機) const arrayLists = await promiseAll; console.log(arrayLists); // 1秒後 // [[' banana', 'tomato'], ['orange', 'apple']] } promiseResult()
2つのPromiseすべてを配列に追加し、一連のPromiseを受け取り、新しいPromiseを返し、すべてのPromiseを同時に実行します。
上記では1秒後に同時実行されています。
const promiseResult = async () => { const promiseAll = Promise.all([ promiseTime1(["banana", "tomato"], 1000), promiseTime2(["orange", "apple"], 1000) ]);
下記の出力をアラート通知にしましたのでご確認下さい。
See the Pen JSのasync/await 並列処理 by dev.K | Webアプリ開発者 (@enjinia_f) on CodePen.
1つのPromiseが拒否された場合、メソッドは短絡してエラーをスローします。
これを正常に実行するには、すべてのPromiseを解決する必要があります。
その際はcatch
を使用下さい。
const promiseResult = async () => { const promiseAll = Promise.all([ promiseTime1(["banana", "tomato"], 1000), promiseTime2(["orange", "apple"], 1000) ]) catch(err) { console.error(err) }
エラー処理については、後ほど詳しく解説致します。
他の例でも、見てみましょう。
以下は、複数の非同期処理を並列実行する例を示しています。
const result = async () => { const promise1 = getResult1(); const promise2 = getResult2(); const promise3 = getResult3(); const [first, second, third] = await Promise.all([promise1, promise2, promise3]); console.log(first); console.log(second); console.log(third); console.log('完了しました!'); }
Promise.allメソッドは、与えられた複数のプロミスを並列実行し、全てのプロミスが解決(完了)した時点で解決される新しいプロミスを返します。
await Promise.all([...])
により、複数の非同期処理が並列実行され、それぞれの結果をまとめて取得することができます。
これにより、非同期処理の実行時間を短縮することができます。
ただし、注意点として、並列実行する非同期処理の数には制限があります。同時に大量の非同期処理を実行しようとすると、システムのリソースを過度に消費する可能性があります。適切な並列実行の数を選択する必要があります。
async/awaitでのループ
async関数をループ内で使用すると、いくつかの注意点や誤解を招く可能性があります。
初心者の方々は、ループが停止したり機能しなかったりするなど、問題に直面することがよくありますので、注意が必要です。
これは、コールバック型の非同期関数が親のasync関数を中断できないために起こる問題です。
具体的には、アロー関数を使用している場合、それがブロックとして機能していることに気づかない可能性があります。
ただし、async関数の使用は、多くの開発者にとってハードルとなっています。
そのほとんどは、配列のループと組み合わせた場合に起こるものです。
配列の要素に対して非同期操作を行う場合、「for...of」または「for」ループが最も簡単な選択肢でしょう。
一方、「forEach」はタスクの完了を待たずに次のコードを実行するため、同期的な動作をします。
コールバックを使用すると、残りのコードが実行され、非同期操作が待機されなくなります。
つまり、awaitキーワードは、次々とタスクを開始し、進行しながら待機します。
古典的な「for」ループでも問題ありませんが、今回は「for...of」を使って例を見てみましょう。
以下に、正しく動作するコードの例を示します。
const asyncDelay = () => { return new Promise(res => setTimeout(res, 100)) } const result = async (itemData) => { await asyncDelay(); console.log(itemData); } const testArray = async (array) => { for (const itemData of array) { await result(itemData); } console.log('完了!'); } testArray([1, 2, 3])
See the Pen JSのasync/await for…ofループ by dev.K | Webアプリ開発者 (@enjinia_f) on CodePen.
上記の例では、配列内の各要素が順番に処理され、数値が順に出力されることが期待されます。
このコードは、非同期処理を行うための関数と、それらの関数を使用して配列内の要素を順番に処理するテスト関数が含まれています。
まず、asyncDelay
関数は、指定された時間(ここでは100ミリ秒)だけ遅延させる非同期のPromiseを返します。これは、非同期処理をシミュレートするために使用されます。
次に、processItem
関数はitemData
を引数に受け取ります。この関数では、asyncDelay
関数を待機するためにawaitキーワードが使用されています。つまり、asyncDelay
関数が完了するまで待機し、その後にconsole.log(itemData)
が実行されます。
この関数は非同期関数として宣言されているため、Promiseを返します。
そして、processArray
関数は配列を引数として受け取ります。この関数では、for...of
ループを使用して配列の各要素を順番に処理します。ループの中で、各要素を引数としてprocessItem
関数を非同期に実行します。
つまり、processItem
関数が完了するまで待機し、次の要素を処理します。最後に、全ての要素の処理が完了した後にconsole.log('完了!')
が実行されます。
したがって、上記のコードは、与えられた配列内の要素を非同期に処理し、各要素の処理が完了した後に「完了!」と表示するものです。
Promise.all()
を使用すれば、この処理を並列して実行する事も可能ですが、注意が必要です。
先述で学んだきた、並列処理と混同しないように気をつけて下さい。
Promise.all()
のasync配列要素は必ずしも並列処理を保証しているわけではない事を忘れないで下さい。
const asyncDelay = () => { return new Promise(res => setTimeout(res, 100)) } const result = async (itemData) => { await asyncDelay(); console.log(itemData); } const testArray = async (array) => { const parallel = array.map(result); await Promise.all(parallel); console.log('完了!'); } testArray([1, 2, 3])
See the Pen JSのasync/await 並行ループ by dev.K | Webアプリ開発者 (@enjinia_f) on CodePen.
上記では、1つ目の非同期処理が完了するまで、2つ目の非同期処理は開始されません。
同様に、2つ目の非同期処理が完了するまで、3つ目の非同期処理は開始されません。
そのため、await Promise.all(parallel)
を使用しても、各非同期処理は順番に実行されます。Promise.all()
はすべての非同期処理が完了するまで待機しますが、各非同期処理が並列に実行されるわけではありません。
したがって、このコードでは実際には直列処理されており、並列処理は行われていません。
このように、array.map()
を使用して並列処理を行った場合、各非同期関数が自動的に並列で実行されるわけではありません。
実行環境やJavaScriptエンジンの実装によっては、非同期処理が逐次的に実行されることがあります。
ただし、複数の非同期処理が同時に実行されることもあります。
もし、確実に並列処理を行いたい場合は、より高度な手法やライブラリを使用する必要があります。
例えば、Promise.all()
を使用して複数の非同期処理を待機する代わりに、並列処理の制御を行うためのライブラリやフレームワーク(例:async/awaitやPromiseの組み合わせ、Promise.race()など)を使用することです。
エラー処理
作成したプログラムでは常にエラーが発生する可能性があります。
特に現代のJavaScript非同期プログラミングでは、ファイルを読み込もうとすると、ファイルが利用できない場合があります。
ですのでasync/awaitでのエラー処理は、多くの混乱を引き起こします。
async関数のエラーを処理するためのパターンは多数あり、経験豊富な開発者でさえ、間違えることがあります。
JavaScriptの非同期プログラミングでは、エラーハンドリングが重要な要素となります。
async/awaitを使用する場合、エラーを処理する方法についていくつかのパターンがあります。
まずは、最も一般的で簡単な方法を紹介します。
async関数からスローされたエラーは、拒否(reject)されたPromiseとなります。
Promiseが正常に解決された場合await promiseの結果を返します。
ただし、拒否された場合は、throw
でその行にawait promise
があるかのようにエラーがスローされます。
const x = async () => { await Promise.reject(new Error("Warning!")); }
同等になります。
const x = async () => { throw new Error("Warning!"); }
throw error
の場合では、その場所で呼び出された場合と同じように、例外が生成されます。
それ以外の場合は、結果を返します。
エラーの処理の際はPromiseが拒否されるまでに、時間がかかる場合があります。
予期しない例外によるプログラムのクラッシュを防ぐために、JavaScriptフロー制御ではエラー処理が非常に重要です。
Promiseでエラーが発生した場合は、async/await構文の最も優れた機能の1つである、同期コードを記述しているのと同じように、標準のtry-catch
が使用可能であることです。
try / catch
const test = async () => { try { const foo = await getFoo(false); } catch (error) { alert(error) // 失敗! } } test()
See the Pen JSのPromiseのasync/await エラー処理 by dev.K | Webアプリ開発者 (@enjinia_f) on CodePen.
素晴らしい機能ですが、async関数内に複数のawaitキーワードがある場合、エラー処理が見にくい可能性があります。
例えば以下のように。
const test = async () => { try { const foo = await getFoo(false); } catch (error) { alert(error) // 失敗! } } try { const foo = await getFoo(false); } catch (error) { alert(error) // 失敗! } } try { const foo = await getFoo(false); } catch (error) { alert(error) // 失敗! } } test()
上記が複雑な処理だった場合、適切にエラー処理するのが大変です。
より良い回避方法がございます。
async関数は常にPromiseを返すことを私たちは学びましたね。
Promiseを呼び出すと、catch呼び出しのエラーを処理できます。
これは、catchを追加することでasync関数からのエラーを適切に処理できることを意味しています。
つまり、async関数は常にPromiseを返すため、Promiseチェーンの中でエラーハンドリングを行うこともできます。この場合、.catch()
メソッドを使用してエラーをキャッチし、適切に処理することができます。
const test = async () => { const result1 = await getResult1(false); const result2 = await getResult2(false); const result3 = await getResult3(false); } test().catch(error); //または test().catch(error => alert(error))
See the Pen JSのasync/await エラー処理 2 by dev.K | Webアプリ開発者 (@enjinia_f) on CodePen.
catch
を追加するのを忘れると、未処理のPromiseエラーが発生します。
注意点は、demoを確認してもらうと分かると思いますが、Promiseのcatchメソッドでは、1つのエラーのみをキャッチできるという点です。
async function innerAsyncFn(){ return Promise.reject(Error("Error from Asynchronous Fn")); }
複数のawaitを待機する場合は、Promiseが解決する前に遅延処理で関数を作成して下さい。
promise.all()メソッドなどの活用です。
複数のPromiseを同時にフェッチもできます。
ほとんどは、すべてをtry / catch
でラップするだけで、快適で安全になります。
.catch()
はasync関数を連鎖(チェーン)させることができる高階関数となります。
エラー処理の方法は様々ございますので、また別途まとめて記事に致します。
async/awaitでFetchを使用する方法
Fetch APIは、純粋なネイティブJavaScriptに付属する非同期Web APIであり、Promiseの形式でデータを返します。
Fetch APIを使用すると、他のAPIと通信が可能となります。
これは、Promiseを使用して『HTTP/1.1プロトコル』を介してネットワーク要求を行うWeb APIとなります。
Fetch APIを使用して、同じリクエストまたはクロスオリジンリクエストの両方を行うができます。
簡単な例をご用意しました。
単純なasyncのGETリクエストを生成しfetchします、ダミー用で提供されている、ユーザーデータを応答オブジェクトからJSON形式で返します。
それではデータベースからユーザーを取得しましょう。
const testRequest = async () => { let url = 'https://jsonplaceholder.typicode.com/users'; let res = await fetch(url); if (res.ok) { let json = await res.json(); alert("成功! データ取得メッセージです"); return json; } else { return `HTTP error: ${res.status}`; } } testRequest().then(data => { console.log(data); });
上記はコールバックを使用しています。
.thenメソッドでPromiseオブジェクトに渡されたコールバック関数の処理結果を取得し、結果を返します。
if(res.ok){}
このok
プロパティは、HTTPステータスコードの200-299
に対してブール値でtrue
を返します。
See the Pen JSのasync/await GETリクエスト by dev.K | Webアプリ開発者 (@enjinia_f) on CodePen.
取得の失敗を出力したい場合は、res.ok
を論理否定演算子でブール値を反転させて下さい、trueからfalseに反転します。
if( !res.ok)
try/catch
でエラー処理する場合は以下のようにします。
const getUsers = async (users) => { try { const response = await fetch(`https://jsonplaceholder.typicode.com/users${users}`); const data = await response.json() if (!data.ok) throw new Error('ユーザーデータの取得に問題があります。'); } catch (error) { console.error(`\u{26A0}Warning: ${error.message}`) } } getUsers('non-user'); 出力: ⚠Warning: ユーザーデータの取得に問題があります。
See the Pen JSのasync/await try/catchでの処理 by dev.K | Webアプリ開発者 (@enjinia_f) on CodePen.
ブロックでエラーが発生した場合、try
ブロック内のコードcatch
が実行されます。
エラーがコンソールに到達して、スクリプトの実行を停止する前に、エラーをキャッチして処理が可能です。
※ 先述でも言いましたが実際では、Promiseがエラーをスローするまでにしばらく時間がかかるので焦らないで下さい。
async関数では、必ず常に何かしらの約束を返すようにします。
使用に関する注意点(ルール)
・ awaitキーワードは通常の関数内で使用することはできません。
const firstAsync = () => { let promise = Promise.resolve(1); let result = await promise; // Syntax error }
function x() { let myPromise = Promise.resolve(1); let result = await myPromise; // Syntax error }
正しく機能させるには、かならず関数の前にasyncを追加する必要がありますので気をつけて下さい。
関数の前にasyncキーワード置くのを忘れると、Syntax error
(構文エラー)が発生する可能性があります。
・ asyncキーワードの後に使用する関数は、awaitである場合とそうでない場合があります。
非同期関数でなければならないという必須の規則はございません。
・ awaitがサポートされていない環境でトップレベルを使用するには、無名関数にトップレベルをラップすることです。
(async () => { const user = await fetch(""); })();
即時関数としてラップしてください。
最後に
Async Awaitは非常に強力となっておりますが、注意も必要です。
しかし、それらを適切に使用すると、コードを非常に読みやすく効率的にするのに役立ちます。
Promise、Observablesへのサブスクリプション、およびsetTimeout()呼び出しはすべて、実行する前にメソッドが完了するのを待つ必要があります。
Promiseベースのasync関数での非同期呼び出しは、あらゆるコールバックパターンを改善しエラーが発生しにくい状態に保ちながら、関数を順番に呼び出し処理することができます。
直感的に理解を望んでる場合は、コードをひたすら書き続け実験かのように繰り返すのが最善の方法です。
動作がおかしいと気付いた際は、なぜそれが発生してしまったのかを理解するように心掛けてください。
JavaScript PromiseのAsync/Awaitについて、精通してる場合の方は、当記事は単純な処理で浅すぎると思われてる方もいらっしゃるとおもいます。
このチュートリアルは、Async/Awaitがどのように機能するかについてより理解を深めてもらい、目標に向けた一歩を踏み出してもらうための、初心者様のプログラマーまたはエンジニアを対象としています。
これで基本的な基礎である、async関数について知っておく必要がある事はありません。
さらに1ステップ進むための、様々なエラー処理方法やJavaScriptでasyncにリソースをfetchする方法も沢山ありますので、それらも今後記事にしていきと思います。
本日は以上となります。
最後までこの記事を読んで頂きありがとうございます。