非同期処理の実装
今回は非同期処理の概要と、Office スクリプトにおける非同期処理の実装方法をサンプルコードと併せて解説します。
非同期処理について
Section titled “非同期処理について”非同期処理とは言葉の通り、同期的に実行されない処理のことを表します。
実装方法の説明の前に、以下のコードをご覧ください。
function fetch(input: RequestInfo, init?: RequestInit): Promise<Response>;これは外部サービスからデータを取得するfetch関数の型定義情報です。
関数の返り値がPromiseでラップされているのが分かると思います。
非同期処理の結果はこのPromiseでラップされます。Promiseは「まだ完了していないかもしれない処理の、将来の結果」を表すオブジェクトです。
async function fetchGoogle() { const response = await fetch('https://www.google.com');
console.log('Googleからデータを取得しました');}
async function main(workbook: ExcelScript.Workbook) { fetchGoogle();
console.log('Googleからデータを取得した後の処理です');}上記のサンプルは、非同期関数fetchGoogleを定義し、main関数から呼び出しています。
fetchGoogleの実装は現段階では「非同期に結果が返ってくる(Promiseを返す)関数」とだけ理解していただければ問題ありません。注目していただきたいのは、main関数の挙動です。
期待する動作はfetchGoogleが完了した後に、main関数内の後続する処理が実行されることだと思いますが、実際の結果は以下のようになります。
Googleからデータを取得した後の処理ですGoogleからデータを取得しました(Office スクリプトでは、待機されていない非同期処理がスクリプトの終了までに完了せず、2 行目が出力されないこともあります。)
main関数内の後続する処理が先に動作してしまっているのが分かります。
このように、非同期処理を待機する命令が指定されていない場合、非同期処理の完了を待たずに後続の処理が実行されます。
async function fetchGoogle() { const response = await fetch('https://www.google.com');
console.log('Googleからデータを取得しました');}async function main(workbook: ExcelScript.Workbook) { await fetchGoogle();
console.log('Googleからデータを取得した後の処理です');}fetchGoogle();の手前にawaitを追加しました。
これであれば、期待した結果を得ることができます。
Googleからデータを取得しましたGoogleからデータを取得した後の処理ですasync/await を使った非同期処理
Section titled “async/await を使った非同期処理”Office スクリプトで最も推奨される非同期処理の記述方法はasync/awaitを使用する方法です。
実行する関数のfunctionの前にasyncを付け、非同期で結果を返す関数の前にawaitを付けることで、非同期関数の結果を取得するまで処理を待機します。
async function main(workbook: ExcelScript.Workbook) { /** Googleのウェブサイトからのレスポンス */ const google = await fetch('https://www.google.com');
console.log('Googleからデータを取得しました');
/** Yahooのウェブサイトからのレスポンス */ const yahoo = await fetch('https://www.yahoo.co.jp');
console.log('Yahooからデータを取得しました');}Promise を使った非同期処理
Section titled “Promise を使った非同期処理”前述した通り、非同期関数の結果はPromiseオブジェクトでラップされているため、Promiseオブジェクトのthenメソッドなどが利用できます。
JavaScript の文法上は、thenを使う場合にasyncは必須ではありません。ただし Office スクリプトで外部呼び出しを行う場合は、main関数にasyncを付け、スクリプトの終了前に処理が完了するようthenのチェーン全体をawaitで待機する必要があります。
async function main(workbook: ExcelScript.Workbook) { await fetch('https://www.google.com') .then((google) => { console.log('Googleからデータを取得しました');
return fetch('https://www.yahoo.co.jp'); }) .then((yahoo) => { console.log('Yahooからデータを取得しました'); });}async/awaitパターンと比較していただくと、このPromise.thenによるメソッドチェーンを使った方法は通常の同期処理と記述方法が大きく異なるため、可読性が低下しかねません。
避けられない場合を除き、async/awaitを使用することをおすすめします。