google-apps-script - 如何每次在 Google Apps 脚本中正确使用 LockService?
问题描述
我试图避免与LockService
我的项目同时进行。
在测试运行中,LockService
对我有用,没有任何问题。
但是当我推出我的项目时,有时LockService
似乎无法正常工作并覆盖电子表格值。
我使用tryLock()
和hasLock()
方法来获取锁。
function test(array) {
var lock = LockService.getScriptLock();
if (lock.tryLock(500)) {
if (!lock.hasLock()) {
var message = "Another user is submitting form data. Please try again later.";
return message;
}
var ss = SpreadsheetApp.openById(outputId);
var sheet = ss.getSheetByName("sheet1");
var lastRow = sheet.getLastRow() + 1;
var range = sheet.getRange(lastRow, 1, 1, array[0].length);
range.setValues(array);
lock.releaseLock();
}
else {
var message = "Another user is submitting form data. Please try again later.";
return message;
}
}
当用户同时提交数据时,我想避免在同一最后一行设置值。但有时它似乎会覆盖最后一行中的值,而其中一个数组的值就消失了。
你能指出我的代码的错误吗?
谢谢你。
解决方案
您应该了解 Lock Service 的各种行为。
tryLock(milliseconds to Wait)
并且waitLock(milliseconds to Wait)
非常相似。一个区别是,这waitLock()
会引发错误,但tryLock()
不会。这意味着您希望程序流程如何工作。您想立即发现错误吗?你不想出错吗?(tryLock() 不会创建和错误)您是否故意想要一个错误?您想要withFailureHandler()
在客户端触发的致命错误吗?你想让整个堆栈都失败吗?您是否希望此功能完全停止,但只是此功能失败?您是否希望只有一条线路出现故障,而其余功能继续运行?
在您的情况下,让函数中的其余行运行毫无意义。
如果你使用waitLock(milliseconds to Wait)
那么你应该有一些东西来捕捉错误。您的选择是:
- 捕捉该行的错误
- 在该函数的任何地方捕获错误
- 不要捕获该函数中的错误
在您的情况下,您不希望函数的其余部分运行。
将错误隔离到一行的一个原因是允许其余代码运行,因为其余代码的结果仍然可以为用户提供一些有用的输出。但这不是你的情况。运行该函数的其余部分,不会为用户提供额外的价值。
事实上,如果你的函数的任何部分失败了,那么它应该停止运行。出于这个原因,我会将函数中的所有行都包装在 try/catch 中。
如果 line:var lock = LockService.getScriptLock();
失败了怎么办?
如果该行失败,则lock
. 如果没有值,lock
则无法释放锁。如果var lock = LockService.getScriptLock();
失败,lock.releaseLock();
则将失败。
这就是我使用的原因:
LockService.getScriptLock().releaseLock();
这就是为什么我不使用变量来锁定。
有两种情况应该释放锁。
- 代码成功完成
- 代码失败
如果在获取锁时代码失败,那么您不希望在释放锁之前让代码等待超时到期。如果到期时间不是很长,那么它可能不是什么大问题。但是如果锁的等待时间长了,那就没有什么好的目的了。如果您的等待时间很短,那么在服务器运行缓慢的情况下,您将面临在代码完成之前锁定到期的风险。所以,我会给你的等待时间一点点填充,但不要太极端。如果您的锁被正确释放,那么等待时间比您需要的时间长一点应该不会产生任何不良影响。如果在很长的等待时间内获得了锁,但不知何故没有被释放,这与没有获得锁一样大。
function myLockFunction() {
try{
//Your entire code inside the try block
LockService.getScriptLock().waitLock(milliseconds);//Throws exception if fail
}catch(e){
LockService.getScriptLock().releaseLock();
}
}
推荐阅读
- c# - 从 .Net 解决方案资源管理器拖放时,如何以编程方式获取文件名?
- android - org.gradle.api.InvalidUserDataException:解决后无法更改配置“:app:debugRuntimeClasspath”的策略错误
- reactjs - 反应嵌套路由问题
- java - P/YC/Y - 从付款 (PMT) 计算未来价值 (FV),每年的复利期 (C/Y)
- javascript - 单击表单中的提交按钮运行 curl 命令
- python-3.x - 复杂的 pandas 聚合
- postgresql - 如何在postgresql中创建“更新多列表后的触发器”?
- ios - 如何使用 UIPanGestureRecognizer 设置拖动控件的边界?
- nativescript - 如何在 Nativescript 的应用程序委托中访问路由器或(存储/获取)数据
- c++ - Windows 10 中的打印不生成文件或作业