我在多次保存同一個條目時遇到問題,我意識到這主要是由雙擊引起的。我正在嘗試使用 LockService 來避免它:如果沒有在一毫秒內獲得鎖,腳本應該被中止(因為它是一個重復的操作)。
//more code above
var lock = LockService.getScriptLock();
try{
lock.waitLock(1);//get the lock timing out in 1 millisecond
SpreadsheetApp.flush();
ss.insertRowBefore(6);
ss.getRange("A6").setValue(data[0][0]);
ss.getRange("B6").setValue(formatedString);
ss.getRange("C6").setValue(data[1][0]);
ss.getRange("D6").setValue(data[2][0]);
ss.getRange("E6").setValue(data[3][0]);
ss.getRange("F6").setValue(data[ref][0]);
SpreadsheetApp.flush();
Utilities.sleep(10);//This is to make sure it takes at least 1 millisecond
}
catch(e){
return;//It should generate a exception and end the script if the lock is not aquired
}
//more code bellow
問題是我仍然收到重復的條目(大多數情況下只有 2 個,所以我相信它部分起作用)。我做錯了什么?
uj5u.com熱心網友回復:
根據您的示例表,在鎖定后續代碼并清除其內容之前,您已經讀取了單元格中的資料。
您的原始代碼:
var data = ss.getRange("B1:B2").getValues();
if(data[0][0] == "" || data[1][0] == "")
return;
var lock = LockService.getScriptLock();
try{
lock.waitLock(1);//get the lock timing out in 1 millisecond
SpreadsheetApp.flush();
ss.insertRowBefore(7);
ss.getRange("A7").setValue(data[0][0]);
ss.getRange("B7").setValue(data[1][0]);
SpreadsheetApp.flush();
Utilities.sleep(10);//This is to make sure it takes at least 1 millisecond
lock.releaseLock();
ss.getRange("B1:B2").setValue("");
}
catch(e){
return;//It should generate a exception and end the script if the lock is not aquired
}
它能做什么?
- 當您多次單擊提交按鈕執行您的代碼時,它將有 n 次執行實體。只要清除單元格不生效,每次執行都可以寫入從
B1:B2.
例子:
Execution 1 started at 01:00:00.001 - already read the values in `B1:B2`
Execution 2 started at 01:00:00.005 - already read the values in `B1:B2`
Execution 3 started at 01:00:00.010 - already read the values in `B1:B2`
執行 1B1:B2在 01:00:00.012清除了內容。因此,您將擁有提交資料的 3 份副本。使用鎖定服務掛起新行中的資料寫入,但未鎖定要添加的資料讀取。
解決方案
function submit() {
Utilities.sleep(1000);//simulate the upper part of the code
var ss = SpreadsheetApp.getActive().getSheetByName("spr1");
var lock = LockService.getScriptLock();
try{
lock.waitLock(1);//get the lock timing out in 1 millisecond
Logger.log("Locked: " Utilities.formatDate(new Date(),Session.getScriptTimeZone(),"yyyy-MM-dd'T'HH:mm:ss.SSS"));
var data = ss.getRange("B1:B2").getValues();
Logger.log(data);
if(data[0][0] == "" || data[1][0] == "")
return;
SpreadsheetApp.flush();
ss.insertRowBefore(7);
ss.getRange("A7").setValue(data[0][0]);
ss.getRange("B7").setValue(data[1][0]);
Utilities.sleep(10);//This is to make sure it takes at least 1 millisecond
ss.getRange("B1:B2").setValue("");
SpreadsheetApp.flush();
lock.releaseLock();
Logger.log("UnLocked: " Utilities.formatDate(new Date(),Session.getScriptTimeZone(),"yyyy-MM-dd'T'HH:mm:ss.SSS"));
}
catch(e){
return;//It should generate a exception and end the script if the lock is not acquired
}
Utilities.sleep(1000);//simulate the lower part of the code
}
更改完成:
- 在讀取資料之前先鎖定腳本
B1:B2 - 確保在釋放鎖之前清除
B1:B2添加到新行中的內容flush()。
輸出:

uj5u.com熱心網友回復:
試試這個方法:
let lock = LockService.getScriptLock();
lock.tryLock(10000);
if (lock.hasLock()) {
ss.insertRowBefore(6);
ss.getRange(6, 1, 1, 6).setValues([data[0][0], formatedString, data[1][0], data[2][0]], data[3][0], data[ref][0])
SpreadsheetApp.flush();
lock.releaseLock();
}
uj5u.com熱心網友回復:
我設法通過添加一個“標志”單元來計算活動提交的數量來解決我的問題。我只在它周圍使用鎖。
var rep = ss.getRange("C1");//the flag starting with 0
var lock = LockService.getScriptLock();
try{
lock.waitLock(1000);
var vAtual = rep.getValue();
if(vAtual >= 1)
return;//return hopefully if it already have one active submission
rep.setValue(vAtual 1);//increment for each active submit
SpreadsheetApp.flush();
lock.releaseLock();
}
catch(e){
return;
}
到目前為止,它并不漂亮,但它奏效了。但是我還是想知道為什么我原來的鎖策略失敗了。它也可以幫助其他一些有類似問題的人。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/358793.html
