はじめに
GoogleAppsScript(GAS)では、doGet/doPost関数を定義することにより、簡易的なWebアプリを作ることもできます。
GASを使ったWebアプリでは、クライアントサーバー間の通信は google.script.run
を使用します1。
google.script.run
は実行が完了するまで少しタイムラグが発生します。また非同期処理となるため、複数回呼び出す必要があったときにネストが深くなってしまう問題(所謂コールバック地獄)もあります。
この問題を回避すべく、 google.script.run
を使わずにスクリプトレット2を使い、スクリプトタグ内に直接オブジェクトを吐き出す方法を紹介します。
スクリプトレット経由でオブジェクトを受け取る
ソースコード
main.gs
var data = {data: 'データ'};
function doGet() {
return HtmlService.createTemplateFromFile('content').evaluate();
}
function getData() {
return data;
}
content.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<script>
window.onload = function () {
// google.script.run使った方法
google.script.run.withSuccessHandler(function (data) {
console.log(data);
}).getData();
// 方法1
var data = <?!= JSON.stringify(data); ?>;
console.log(data);
// 方法2
data = JSON.parse('<?!= JSON.stringify(data).replace(/\\/g, "\\\\"); ?>');
console.log(data);
// 方法3
data // <?!= "\n = " + JSON.stringify(data); ?>;
console.log(data);
}
</script>
</body>
</html>
実行結果
chromeのコンソール画面。
それぞれの方法で問題なくデータが受け取れています。
解説
- 方法1
-
<?!= ~~ ?>
(スクリプトレット)内に書かれたコードはサーバー側で実行され、結果だけがクライアント側で表示されます。 -
JSON.stringify
した結果を、そのままクライアント側のスクリプトの一部として評価しています。
-
- 方法2
- VSCodeだと、スクリプトレットの部分が問題扱いされてしまうため、この部分をシングルクオートで囲み、さらに
JSON.parse
でオブジェクトに変換します。 - そのままだとバックスラッシュが消えてしまうので、スクリプトレット内で置換し二倍に増やしておきます。
- VSCodeだと、スクリプトレットの部分が問題扱いされてしまうため、この部分をシングルクオートで囲み、さらに
- 方法3
- 方法1を何とかVSCodeでも問題扱いされないように書き換えたものです。苦肉の策。
- スクリプトレット内で改行を入れてあるので、クライアント側では二行で表示され、ちゃんと代入されます。
まとめ
google.script.run
を使わずにスクリプトレット経由でオブジェクトを受け取る方法を紹介しました。
スクリプトレットの部分がVSCodeで問題扱いされるため、代わりの方法を考えてみましたが...ちょっと読みにくいかな...
もっとエレガントな解決方法があればぜひ教えてください。