我正在尝试避免在项目上与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;
}
}
当用户同时提交数据时,我想避免在最后一行中设置值。 但是有时似乎会覆盖最后一行中的值,而数组的值之一就消失了。
您能指出我的代码错误吗?
谢谢。
答案 0 :(得分:0)
您应该了解锁定服务的各种行为。
tryLock(milliseconds to Wait)
和waitLock(milliseconds to Wait)
非常相似。一个区别是waitLock()
将引发错误,而tryLock()
不会引发错误。这意味着您希望程序流如何工作。您要立即发现错误吗?您要没有错误吗? (tryLock()不会创建并且出错)您是否故意想要一个错误?您是否需要在客户端触发withFailureHandler()
的致命错误?您是否要使整个堆栈失败?您是否希望此功能完全停止,而只是此功能失败?您是否只希望其中一行失败,而让其余功能继续运行?在您所处的情况下,让函数中的其余行运行毫无意义。
如果使用waitLock(milliseconds to Wait)
,则应该有一些可以捕获该错误的东西。您的选择是:
在您的情况下,您不希望其余部分运行。
将错误隔离到仅一行的原因是允许其余代码运行,因为其余代码的结果仍然可以为用户提供一些有用的输出。但这不是你的情况。运行该功能的其余部分,不会为用户提供任何额外的价值。
实际上,如果函数的 any 部分失败,则它应该停止运行。因此,我会在try / catch中包装函数中的所有行。
如果行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();
}
}
答案 1 :(得分:0)
发生这种情况的原因是电子表格服务可能需要花费一些时间才能由电子表格服务进行更改。您的脚本不会等待电子表格服务提交更改,并且可以在这种情况发生之前释放锁定。
在释放锁之前,应先致电SpreadsheetApp.flush()
,以确保对电子表格所做的所有更改都已提交,然后再允许脚本的新实例对工作表进行更改。
由于您要执行的操作是在表的末尾附加行,因此也可以使用appendRow()
方法,如其他人所建议的那样,并且不需要使用锁定服务。但是我认为您想了解发生了什么,并了解如何正确地将锁定服务与电子表格一起使用,因为将来可能需要这样做。