如何识别是哪个时间驱动触发器调用了Google Apps Script函数
解决方案
你可以通过触发器唯一ID(triggerUid)+ 脚本属性存储的方式区分每日触发器和临时触发器,具体实现逻辑如下:
- 可安装触发器调用目标函数时,会自动传入事件对象,事件对象的
triggerUid字段就是当前触发的触发器的唯一标识 - 创建临时触发器时,将新生成的触发器ID存入脚本属性的临时触发器ID列表中
- 函数执行时首先校验当前触发的触发器ID是否在临时ID列表中,匹配则删除该触发器,同时移除属性中的对应记录
完整可运行代码示例:
function run_job_via_trigger(e) { // 读取存储的临时触发器ID列表,默认是空数组 const scriptProps = PropertiesService.getScriptProperties(); const tempTriggerIds = JSON.parse(scriptProps.getProperty('TEMP_TRIGGER_IDS') || '[]'); // 校验当前是否为临时触发器触发 if (e && e.triggerUid && tempTriggerIds.includes(e.triggerUid)) { // 遍历找到对应的触发器实例删除 const allTriggers = ScriptApp.getProjectTriggers(); for (const trigger of allTriggers) { if (trigger.getUniqueId() === e.triggerUid) { ScriptApp.deleteTrigger(trigger); break; } } // 从临时ID列表中移除当前ID,更新存储 const updatedTempIds = tempTriggerIds.filter(id => id !== e.triggerUid); scriptProps.setProperty('TEMP_TRIGGER_IDS', JSON.stringify(updatedTempIds)); } const job_finished = job_that_takes_several_calls_to_complete(); if (!job_finished) { // 创建1分钟后触发的临时触发器 const newTempTrigger = ScriptApp.newTrigger('run_job_via_trigger') .timeBased() .everyMinutes(1) .create(); // 将新触发器ID存入临时列表 tempTriggerIds.push(newTempTrigger.getUniqueId()); scriptProps.setProperty('TEMP_TRIGGER_IDS', JSON.stringify(tempTriggerIds)); } else { // 任务全部完成后清理所有残留的临时触发器,避免占用配额 const allTriggers = ScriptApp.getProjectTriggers(); const tempTriggerIds = JSON.parse(scriptProps.getProperty('TEMP_TRIGGER_IDS') || '[]'); for (const trigger of allTriggers) { const triggerId = trigger.getUniqueId(); if (tempTriggerIds.includes(triggerId)) { ScriptApp.deleteTrigger(trigger); } } // 清空临时ID存储 scriptProps.deleteProperty('TEMP_TRIGGER_IDS'); } } function job_that_takes_several_calls_to_complete() { // 该函数的运行时长通常超过脚本允许的最大时长,会跟踪自身执行时长 // 若任务全部完成则返回true,若需要更多运行时间需再次调用则返回false return finished ? true : false; }
补充说明:
- 该方案不会影响项目中其他触发器的正常运行,也不需要改动原有每日触发器的配置
- 任务完成时会自动清理所有临时触发器,不会产生冗余触发器占用脚本配额
内容的提问来源于stack exchange,提问作者x-x
相关产品推荐
相关产品推荐

