回想當初剛開始寫GAS專案時,不知道為什麼對於「內建的triggers」這個概念有點想不通,it works fine,但就說不出哪裡怪。直到實作
doGet
時才突然搞懂:啊,就只是這樣嘛!
GAS環境有一些保留函式(reserved functions),它們既不是昨天(Day04)提到的Google Workspace API,也不屬於前天(Day03)提到的GAS環境特有的全域變數,今天就讓我簡單聊聊這些simple triggers。[^1]
在瀏覽器環境,我們會設計UI與listener/handler;在GAS環境,有一些事件[^2]不需要開發者手動於UI綁listener,這類simple triggers就類似瀏覽器環境的handler。相較其它服務,其權限較小,從而也不需要額外設定或產生同意確認彈窗。
比如使用者開啟Google Sheets[^3],或開發者於Node.js環境向Google Sheets發送HTTP GET請求,GAS環境會搜尋專案內是否有對應的triggers,如果有就會call它們。
換言之,這些simple triggers都是GAS環境的保留函式,必須由開發者自行宣告由GAS指定的、保留的trigger名稱,當事件發生時,才能被invoke。而且,必須宣告於top-level,也就是triggers必須位於global scope。
其中,onEdit
和onOpen
幾乎在每個專案中我都會使用到,這邊是曾經實作過的例子:
使用onOpen來載入native-like選單:
function onOpen() {
const ui = SpreadsheetApp.getUi();
ui.createMenu("綜合檢視")
.addItem("綜合標示", "highlight")
.addItem("清除所有標示", "clearHighlight")
.addToUi();
}
使用onEdit來記錄特定欄位之最後編輯時間:
function onEdit(e) {
const range = e.range;
if (
range.getNumColumns() !== 1 ||
range.getColumn() !== 3 ||
range.getRow() === 1
) {
return;
}
const currentTime = new Date();
const targetCell = range.offset(0, -2);
targetCell.setValue(currentTime);
}
同樣是simple triggers,doGet
和doPost
則必須將GAS專案部署為Web App,當外部環境向Web App[^4]發起HTTP GET或POST請求時,才會去call它們。
function doGet(event) {
try {
return ContentService.createTextOutput(
JSON.stringify({
status: "ok",
code: 200,
message: "The secret meetup spot of the Deno cult retrieved successfully",
data: {
meetupSpot: denoland,
},
})
).setMimeType(ContentService.MimeType.JSON);
} catch (error) {
return ContentService.createTextOutput(
JSON.stringify({
status: "error",
code: 500,
message: `Unexpected error: ${error.message}`,
})
).setMimeType(ContentService.MimeType.JSON);
}
}
總之,GAS環境提供一些保留函式,除了使用者操作觸發,也可以部署成APP並透過保留函式自定義要回傳的值。
回想當初剛開始寫GAS專案時,不知道為什麼對於「內建的triggers」這個概念有點想不通,會用是會用,但就說不出哪裡怪。直到實作doGet
時,在GAS環境與Deno環境分別寫了腳本串接資料,才遲遲意識到,其實它就只是一個「指定好名稱的callback function」,有一種把散亂的拼圖連接起來的感受。
我覺得挺有趣的是,查了一下,才知道原來更早的年代,瀏覽器環境也有過onload
和onerror
這種保留函式,那時addEventListener
甚至還沒被開發者們普遍使用。
[^1]: https://developers.google.com/apps-script/guides/triggers
[^2]: 順道一提,不影響寫專案的冷知識:不同於瀏覽器環境,GAS環境的event並非WHATWG DOM Event API標準的instance,而是JSON-like object。
[^3]: 這些simple triggers主要是對應使用者於GUI上的操作,對於GAS腳本所觸發的事件則否。
[^4]: 還有另一個部署選項是Execution API,讓外部環境可以使用專案內的函式,但需要設定OAuth。