トリガー実行時のメソッドに引数を設定するときの注意点【GAS(Google Apps Script)】

TIPS

こんにちは。ざわかける!のざわ(@zw_kakeru)です。
GAS(Google Apps Script)を用いてスクリプト内で実行トリガーを作成、設定する際に、指定メソッドに引数を用いるときの注意点(私がハマった箇所)についてのTipsです。
第一引数にトリガーオブジェクトが入ってしまうので、実装時にはそこを回避してあげましょう。
引数設定がうまくできない人は参考にしてください。

動作環境

Google Apps Script: June, 1, 2021 (latest)

やったことと起きたこと

別記事「TwitterAPIを使ってライバロリさんにDMを送るbotを作る【GAS(GoogleAppsScript)】」で紹介しているbot作成作業をしていた時のことです。



GAS(Google Apps Script)において、スクリプトによって自動生成されたトリガーを用いてメソッドを実行しようとしました。

function setTrigger(funcName) {
  if (funcName == undefined) { funcName = "HogeFunc" }

  const time = new Date();
  time.setHours(time.getHours() + 1); 
  ScriptApp.newTrigger(funcName).timeBased().at(time).create();
}

setTriggerメソッドを実行するとちょうど1時間後に起動するトリガーが作成されます。
そしてその時間になるとトリガーによってHogeFuncが実行される、という仕様になっています。
このsetTriggerメソッド、引数としてメソッド名(funcName)を指定するようになっています。
HogeFunc以外のメソッドをトリガー実行したくなった時に再利用しやすいようにこのような書き方をしました。
引数が与えられなかった場合には2行目でHogeFuncが指定されます(すなわちHogeFuncがデフォルト値となるようにしています)。

これを通常実行すると特に問題もなくトリガー生成ができるのですが、私はさらにこのsetTriggerメソッドをトリガー実行しようとしました。
GASエディタ上からsetTriggerの定期実行設定を行い、実行時間になった後で設定確認を行うとこのようになっていました。

(ん、関数名がおかしなことになっている。)
トリガー設定した関数名はHogeFuncのはずなんですけど、これってどう見てもトリガーオブジェクトそのものが表示されていますよね、、、ワケワカンナイヨー!

これじゃあ時間になってもHogeFuncを実行することができません。困った。

わかったことと解決策

ここからが本題、というか結論です。
GASでトリガー実行する際は、実行されるメソッドの第一引数にそのトリガーオブジェクトそのものが設定されるようです。
それにより、上記のスクリプトでは引数funcNameにそのトリガーオブジェクトが渡されていたため、2行目で(undefinedではないために)初期化が行えずにメソッド名としてそのまま新しいトリガーが生成されてしまった、という流れになってしまったよようですね。

解決策としては、第一引数を避けて第二引数から本来使いたい引数を設定する方法が挙げられます。

function setTrigger(_, funcName) {
  if (funcName == undefined) { funcName = "HogeFunc" }

  const time = new Date();
  time.setHours(time.getHours() + 1); 
  ScriptApp.newTrigger(funcName).timeBased().at(time).create();
}

受ける引数を二つに増やすことで、無事にsetTriggerメソッドのトリガー実行でfuncNameが初期化され、HogeFuncのトリガーを設定できました。

まあしかし、元々汎用性を持たせるためにメソッド名を引数指定していたはずなんですけど、これはこれで本末転倒感。。

ざわ
ざわ

ていうか冷静に考えたら、トリガーってイベント発火なんだから第一引数でそのイベントを(本来eとかの変数で)受け取るは当たり前なのでは。。。

終わりに

結論までさらっと書いていますが、結構盛大に(約2時間)ハマりました。
勉強不足ですねえ。
しかし、記事を書いている間に私の理解がモリモリ進んだので良しとします。

…そういえばトリガー実行時の正しい引数の渡し方については結局調べていませんね。
ちゃんとしたやり方があるなら私のようにハマる人はいないのでしょう。

この辺りってなんかいつの間にか仕様が変わってそうな気がするので、やっぱり引数は使わずにメソッド内で変数宣言した方がいいのでしょうか。
でもそのようなハードコーディングは個人的にあまり好きじゃないんですよね。。
じゃあだからと言って今のこの書き方がキレイかと言われるとそれも違いますが。。。

タイトルとURLをコピーしました