App Script场景下Slides API批量更新的队列并发冲突如何解决?
解决方案
方案1:使用内置LockService处理并发(优先推荐)
Apps Script提供了原生的LockService服务,专门用于解决多实例并发执行的资源冲突问题,你可以将「读取队列号→更新队列号→调用Slides API」的整个临界区逻辑加入排他锁,保证同一时间只有一个脚本实例执行这段代码,从根源避免队列号重复:
// 获取排他锁,最长等待30秒 const lock = LockService.getScriptLock(); try { lock.waitLock(30000); // 原有的队列读写逻辑 var array = sessionsSheets.getRange(row, 2, 1, 3).getValues()[0]; var questionNumber = array[2]; // 建议把setFormula改成setValue直接写入固定值,避免公式二次计算带来的意外问题 sessionsSheets.getRange(`D${row}`).setValue(questionNumber + 1); // 调用Slides API Slides.Presentations.batchUpdate({'requests': requests}, presentationId); } catch (e) { // 可在这里添加错误日志记录逻辑 throw e; } finally { // 执行完务必释放锁,避免其他实例等待超时 lock.releaseLock(); }
方案2:同步重试机制
如果你不需要严格控制执行顺序,也可以用同步重试逻辑实现冲突重试,不需要Promise支持:
const MAX_RETRY = 5; // 最大重试次数,避免死循环 let retryCount = 0; let success = false; while (!success && retryCount < MAX_RETRY) { try { // 每次重试都重新读取最新的队列号 var array = sessionsSheets.getRange(row, 2, 1, 3).getValues()[0]; var questionNumber = array[2]; sessionsSheets.getRange(`D${row}`).setValue(questionNumber + 1); Slides.Presentations.batchUpdate({'requests': requests}, presentationId); success = true; } catch (e) { // 判断是否是队列号重复导致的错误,只有该类错误才重试,替换成实际报错的特征内容即可 if (e.message.includes('队列号重复相关的错误特征字符串')) { retryCount++; Utilities.sleep(100 * retryCount); // 指数退避等待,降低再次冲突的概率 } else { // 非重复类错误直接抛出 throw e; } } } if (!success) { throw new Error('重试次数已达上限,队列号冲突仍未解决'); }
额外优化建议
- 队列号的更新尽量用
setValue写入固定数值,避免setFormula引入的公式计算延迟、多实例同时触发公式计算的额外冲突问题 - 如果队列号使用频率很高,也可以将队列号存储在
PropertiesService中,读写速度比电子表格更快,锁冲突概率更低
内容的提问来源于stack exchange,提问作者Mike Harb
相关产品推荐
相关产品推荐

