Google Apps Script:如何避免两个按钮触发的函数同时运行?
确保两个Google Apps Script函数互斥执行的解决方案
你之前尝试的Lock类没生效,大概率是锁的类型选错或者使用方式不对。针对跨用户的互斥需求,应该使用脚本级锁(ScriptLock),它能在所有用户的脚本执行之间建立互斥机制,确保同一时间只有一个函数(a或b)在运行。
正确实现代码
function a() { // 获取脚本级锁,所有用户共享 const lock = LockService.getScriptLock(); // 尝试获取锁,设置30秒超时(可根据业务调整) if (!lock.tryLock(30000)) { // 拿不到锁时提示用户,也可改为静默返回或日志记录 SpreadsheetApp.getUi().alert("当前有其他操作正在进行,请稍后再试"); return; } try { // 这里写入函数a的业务逻辑 // 示例:SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").appendRow([new Date(), "执行函数a"]); } finally { // 无论成功/失败,必须释放锁,避免死锁 lock.releaseLock(); } } function b() { const lock = LockService.getScriptLock(); if (!lock.tryLock(30000)) { SpreadsheetApp.getUi().alert("当前有其他操作正在进行,请稍后再试"); return; } try { // 这里写入函数b的业务逻辑 // 示例:SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet2").appendRow([new Date(), "执行函数b"]); } finally { lock.releaseLock(); } }
关键注意事项
- 锁的类型选择:必须用
LockService.getScriptLock(),而不是getDocumentLock()或getUserLock()。后两者作用范围有限:getDocumentLock()在部分跨用户场景下可能存在上下文漏洞,getUserLock()仅限制当前用户的操作,无法阻止其他用户同时执行。 - 超时与返回逻辑:用
tryLock()而非waitLock(),waitLock()会无限等待直到拿到锁,容易触发脚本超时;tryLock()可设置超时时间,拿不到锁时直接提示用户退出,避免阻塞。 - 锁的释放:必须在
finally块中调用releaseLock(),确保即使函数执行中抛出异常,锁也能被释放,不会导致后续所有操作都无法获取锁。 - 优化执行效率:锁内的业务逻辑尽量精简,避免耗时过长的操作,减少其他用户的等待时间。
内容的提问来源于stack exchange,提问作者Melicent Rouméas
相关产品推荐
相关产品推荐

