如何在 Google Apps 脚本中每次正确使用 LockService?
How do I use LockService properly every time in Google Apps Script?
我试图避免在我的项目中与 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()
的致命错误吗?你想让整个堆栈都失败吗?您是否希望此功能完全停止,而只是此功能失败?您是否希望只有一行失败,而函数的其余部分保持 运行ning?
在您的情况下,将剩余的行放在函数 运行 中没有意义。
如果你使用 waitLock(milliseconds to Wait)
那么你应该有一些东西来捕捉错误。您的选择是:
- 捕获该行的错误
- 在该函数的任何位置捕获错误
- 不要捕获该函数中的错误
在您的情况下,您不希望拥有函数的其余部分 运行。
将错误隔离到一行的一个原因是允许其余代码 运行,因为其余代码的结果仍然可以为用户提供一些有用的输出。但这不是你的情况。拥有该功能的其余部分 运行,不会为用户提供额外的价值。
事实上,如果 任何 函数的一部分失败,那么它应该停止 运行ning。出于这个原因,我会将函数中的所有行包装在 try/catch.
中
如果行:var lock = LockService.getScriptLock();
失败怎么办?
如果该行失败,则 lock
将没有值。如果 lock
没有值那么你就不能释放锁。如果 var lock = LockService.getScriptLock();
失败,那么 lock.releaseLock();
也会失败。
这就是我使用的原因:
LockService.getScriptLock().releaseLock();
这就是我不为锁使用变量的原因。
有两种情况需要释放锁。
- 代码成功完成
- 代码失败
如果代码在获取锁时失败,那么您不希望代码在释放锁之前等待 time-out 过期。如果有效期不是很长,那么这可能不是什么大问题。但是如果锁等待时间长了,那就是白白等待了。如果您的等待时间很短,那么在服务器 运行 速度缓慢的情况下,您 运行 有在代码完成之前锁定过期的风险。所以,我会给你的等待时间一点点填充,但不要太极端。如果您的锁被正确释放,那么等待时间比您需要的时间长一点应该不会有任何不良影响。如果在很长的等待时间内获得了锁,但不知何故没有被释放,这与没有获得锁一样是一个问题。
function myLockFunction() {
try{
//Your entire code inside the try block
LockService.getScriptLock().waitLock(milliseconds);//Throws exception if fail
}catch(e){
LockService.getScriptLock().releaseLock();
}
}
发生这种情况的原因是点差sheet 的更改可能需要一些时间才能由点差sheet 服务完成。您的脚本不会等待 Spreadsheet 服务提交更改并可能在此之前释放锁定。
您应该在释放锁定之前调用 SpreadsheetApp.flush()
以确保在您的脚本的新实例被允许对您的 sheet 进行更改之前提交您对传播 sheet 所做的所有更改。
由于您正在做的是将行附加到 sheet 的末尾,您也可以使用 appendRow()
方法,正如其他人所建议的那样,您不需要使用锁定服务。但我想你想了解发生了什么,并学习如何与 Spreadsheets 一起正确使用锁定服务,因为你将来可能需要这样做。
我试图避免在我的项目中与 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()
的致命错误吗?你想让整个堆栈都失败吗?您是否希望此功能完全停止,而只是此功能失败?您是否希望只有一行失败,而函数的其余部分保持 运行ning?
在您的情况下,将剩余的行放在函数 运行 中没有意义。
如果你使用 waitLock(milliseconds to Wait)
那么你应该有一些东西来捕捉错误。您的选择是:
- 捕获该行的错误
- 在该函数的任何位置捕获错误
- 不要捕获该函数中的错误
在您的情况下,您不希望拥有函数的其余部分 运行。
将错误隔离到一行的一个原因是允许其余代码 运行,因为其余代码的结果仍然可以为用户提供一些有用的输出。但这不是你的情况。拥有该功能的其余部分 运行,不会为用户提供额外的价值。
事实上,如果 任何 函数的一部分失败,那么它应该停止 运行ning。出于这个原因,我会将函数中的所有行包装在 try/catch.
中如果行:var lock = LockService.getScriptLock();
失败怎么办?
如果该行失败,则 lock
将没有值。如果 lock
没有值那么你就不能释放锁。如果 var lock = LockService.getScriptLock();
失败,那么 lock.releaseLock();
也会失败。
这就是我使用的原因:
LockService.getScriptLock().releaseLock();
这就是我不为锁使用变量的原因。
有两种情况需要释放锁。
- 代码成功完成
- 代码失败
如果代码在获取锁时失败,那么您不希望代码在释放锁之前等待 time-out 过期。如果有效期不是很长,那么这可能不是什么大问题。但是如果锁等待时间长了,那就是白白等待了。如果您的等待时间很短,那么在服务器 运行 速度缓慢的情况下,您 运行 有在代码完成之前锁定过期的风险。所以,我会给你的等待时间一点点填充,但不要太极端。如果您的锁被正确释放,那么等待时间比您需要的时间长一点应该不会有任何不良影响。如果在很长的等待时间内获得了锁,但不知何故没有被释放,这与没有获得锁一样是一个问题。
function myLockFunction() {
try{
//Your entire code inside the try block
LockService.getScriptLock().waitLock(milliseconds);//Throws exception if fail
}catch(e){
LockService.getScriptLock().releaseLock();
}
}
发生这种情况的原因是点差sheet 的更改可能需要一些时间才能由点差sheet 服务完成。您的脚本不会等待 Spreadsheet 服务提交更改并可能在此之前释放锁定。
您应该在释放锁定之前调用 SpreadsheetApp.flush()
以确保在您的脚本的新实例被允许对您的 sheet 进行更改之前提交您对传播 sheet 所做的所有更改。
由于您正在做的是将行附加到 sheet 的末尾,您也可以使用 appendRow()
方法,正如其他人所建议的那样,您不需要使用锁定服务。但我想你想了解发生了什么,并学习如何与 Spreadsheets 一起正确使用锁定服务,因为你将来可能需要这样做。