如何在 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 一起正确使用锁定服务,因为你将来可能需要这样做。