非同期処理の実装
今回は非同期処理の概要と、Office スクリプトにおける非同期処理の実装方法をサンプルコードと併せて解説します。
非同期処理について
非同期処理とは言葉の通り、同期的に実行されない処理のことを表します。
実装方法の説明の前に、以下のコードをご覧ください。
function fetch(input: RequestInfo, init?: RequestInit): Promise<Response>;
これは外部サービスからデータを取得するfetch
関数の型定義情報です。
関数の返り値がPromise
でラップされているのが分かると思います。
非同期処理の結果は全てこのPromise
でラップされ、「結果が返ってきているか分からない状態」を表します。
async function fetchGoogle() {
const response = await fetch('https://www.google.com');
console.log('Googleからデータを取得しました');
}
function main(workbook: ExcelScript.Workbook) {
fetchGoogle();
console.log('Googleからデータを取得した後の処理です');
}
上記のサンプルは、非同期関数fetchGoogle
を定義し、main
関数から呼び出しています。
fetchGoogle
の実装は現段階では「非同期に結果が返ってくる(Promise
を返す)関数」とだけ理解していただければ問題ありません。注目していただきたいのは、main
関数の挙動です。
期待する動作はfetchGoogle
が完了した後に、main
関数内の後続する処理が実行されることだと思いますが、実際の結果は以下のようになります。
Googleからデータを取得した後の処理です
Googleからデータを取得しました
main
関数内の後続する処理が先に動作してしまっているのが分かります。
このように、非同期処理を待機する命令が指定されていない場合、Promise
でラップされた非同期処理の結果は、完了を待たずして後続の処理が実行されます。
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からデータを取得した後の処理です');
}
main
関数のfunction
の前にasync
を、fetchGoogle();
の手前にawait
を追加しました。
これであれば、期待した結果を得ることができます。
Googleからデータを取得しました
Googleからデータを取得した後の処理です
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 を使った非同期処理
前述した通り、非同期関数の結果は全てPromise
オブジェクトでラップされているため、Promise
オブジェクトのメソッドが利用できます。
この場合は、function
の手前にasync
を付ける必要はありません。
function main(workbook: ExcelScript.Workbook) {
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
を使用することをおすすめします。