GASで重たい処理中にローディング表示する
ファイルの読み書き中やAPIの呼び出し時に、
ローディング表示したいなと思ったので作ってみました。
概要
- GASからモーダルダイアログを呼び出し
- モーダルダイアログでローディング表示している裏で重たい処理を実行
- 処理が完了したらダイアログ側に結果を通知
手順
重たい関数を作る
6分を超えない範囲で重たい処理を実装しましょう
モーダルダイアログに情報を返したい時は
- 正常終了時:
return
で戻り値を返す - 異常終了時:
throw
でエラーオブジェクトを返す
とすることで、モーダル側で処理を分けることが出来ます
function verySlowFunc() {
// 時間のかかる処理
Utilities.sleep(3 * 1000);
// 終了時に表示する文字列
return 'Success';
// 失敗時は例外を投げる
// throw new Error('Failuer!');
}
ローディング画面を呼び出す部分を作る
モーダルダイアログを呼び出す処理を作成します。
ダイアログはクライアントサイドで動くので
サーバーサイドから渡したい情報は、グローバル変数を利用して共有します。
※このケースでは、関数名を文字列として受け渡し
/** ローディング画面に受け渡すためのグローバル変数 */
let loading_cb = '';
/** ローディング画面の呼び出し*/
function beginLoading() {
// ローディング中に実行する関数をコールバックに指定
loading_cb = 'verySlowFunc';
const html = HtmlService
.createTemplateFromFile('load.html')
.evaluate();
SpreadsheetApp.getUi().showModalDialog(html, '重たい処理...');
}
ローディング画面を実装する
こんな感じでhtmlを書きましょう。
GASのIDEでファイル追加すればOKです
以下の箇所で、サーバーサイドでセットした
グローバル変数を参照して、callBack
関数に渡します。
<script type="text/javascript">
window.onload = (_ => {
google
.script
.run
.withSuccessHandler(onSuccess)
.withFailureHandler(onFailure)
.callBack(<?= loading_cb ?>); // コールバック関数を読み込む
});
</script>
GASにはScriptletという仕組みがあり、
こんな感じのフォーマットで記述した部分は事前にサーバーサイドで実行された後でHTMLとして解釈されます
<?= loading_cb ?>
コールバック用APIを作成する
モーダル(クライアントサイド)から呼び出すための関数を作成します。
本当は関数オブジェクトを直接渡して実行したい所ですが、
クライアントサイドのgoogle.script.run
で指定可能な関数は
HTMLファイル毎に固定なので汎用性があまり高くありません。
そのため、関数名の文字列をキーとしたテーブルを用意して
コールバック用APIに渡された文字列に対応した関数を呼び出す設計にしています。
/**
* ローディング画面からのコールバック用関数
* @param[in] {string} func 呼び出す関数名
*/
function callBack(func) {
// コールバックテーブル
const callBackTable = {
'verySlowFunc': () => verySlowFunc(),
};
// コールバック関数実行
if(callBackTable[func])
return callBackTable[func]();
// テーブルに無ければエラー
throw new Error('no callback');
}
こうすることで、1つのload.html
に対して
複数のコールバック関数を割り当てることが可能になり、
コードの見通しが良くなりました
まとめ
今回はローディング画面のコールバック関数という形で
サーバーサイドとクライアントサイドの連携を行いました。
どちらもJavascriptベースで処理が書けるので、
慣れれば割と簡単に意図した処理が実現出来るかと思います🙌