Concurrency 访问电子表格时锁定脚本无效
我的问题是如何确保并发访问时不会丢失数据 我已将脚本发布为web应用程序。我想在数据表中添加新行。处理“提交”按钮的函数如下所示:Concurrency 访问电子表格时锁定脚本无效,concurrency,google-apps-script,google-spreadsheet-api,Concurrency,Google Apps Script,Google Spreadsheet Api,我的问题是如何确保并发访问时不会丢失数据 我已将脚本发布为web应用程序。我想在数据表中添加新行。处理“提交”按钮的函数如下所示: function onButtonSubmit(e) { var app = UiApp.getActiveApplication(); var lock = LockService.getPublicLock(); while (! lock.tryLock(1000)) ; var ssheet = SpreadsheetApp.open
function onButtonSubmit(e) {
var app = UiApp.getActiveApplication();
var lock = LockService.getPublicLock();
while (! lock.tryLock(1000))
;
var ssheet = SpreadsheetApp.openById(SHEET_ID);
var sheet = ssheet.getSheetByName(DATA_SHEET);
var lastRow = sheet.getLastRow();
var lastCol = sheet.getLastColumn();
var rangeToInsert = sheet.getRange(lastRow+1, 1, 1, lastCol);
var statText = rangeToInsert.getA1Notation();
rangeToInsert.setValues(<some data from webapp form>);
app.getElementById('statusLabel').setText(statText);
lock.releaseLock();
return app;
}
功能按钮提交(e){
var app=UiApp.getActiveApplication();
var lock=LockService.getPublicLock();
而(!lock.tryLock(1000))
;
var ssheet=电子表格应用程序openById(表格ID);
var sheet=ssSheet.getSheetByName(数据表);
var lastRow=sheet.getLastRow();
var lastCol=sheet.getLastColumn();
var rangeToInsert=sheet.getRange(lastRow+1,1,1,lastCol);
var statText=rangeToInsert.geta1表示法();
rangeToInsert.setValues();
app.getElementById('statusLabel').setText(statText);
锁。释放锁();
返回应用程序;
}
但这似乎不起作用。当我在一秒钟内打开两个表单并单击submit按钮时,它会在statsLabel中显示相同的范围,并将数据写入相同的范围。所以我丢失了一个表单中的数据
这个代码有什么问题?看起来tryLock()不会阻止脚本
有没有其他方法可以防止对工作表的并发写访问
while (! lock.tryLock(1000))
;
看起来有点可疑。请尝试以下方法:
if (lock.tryLock(30000)) {
// I got the lock! Wo000t!!!11 Do whatever I was going to do!
} else {
// I couldn’t get the lock, now for plan B :(
GmailApp.sendEmail(“admin@example.com”, “epic fail”,
“lock acquisition fail!”);
}
它可能值得一看,而不是使用
getLastRow()
/setValues()
等
允许在电子表格中以原子方式追加一行;可以使用
即使脚本的多个实例同时运行,也是安全的
同时。以前,必须调用getLastRow(),然后写入
到那一排。但是如果脚本的两次调用同时运行
同时,它们可能都读取getLastRow()的相同值,并且
然后覆盖彼此的值
使用带锁的getLastRow()/setValues()时,必须插入此代码
SpreadsheetApp.flush();
// before
lock.releaseLock();
我想等到锁被另一个实例释放。如果它从未被释放呢?如果第一个用户离开他的计算机怎么办?你的策略应该是只在你需要写作的时候锁定,而且写作不应该花那么长时间,真的。如果你的竞争对手是两个以上的用户,你需要一个更好的解决方案,比如数据库。是的,一些数据库是更好的解决方案,但我必须在谷歌电子表格中这样做。无论如何,我可以在n次迭代后中断while循环,然后以错误消息结束。尝试写入新行时,我仅在提交按钮处理程序中使用锁定。我尝试了您的解决方案,但它不起作用。两个提交的表单几乎同时将数据写入同一行。谢谢,我将在明天尝试。这是比锁定更好的解决方案。似乎锁定web应用程序是一个很好的解决方案