gpt4 book ai didi

google-apps-script - 具有超时保护的循环仅运行一次 "as it should"

转载 作者:行者123 更新时间:2023-12-02 06:05:35 25 4
gpt4 key购买 nike

我编写了一个脚本,可以从电子表格中写入的备份恢复日历数据。由于数据量高度不可预测,我设计了一个在给定分钟数后停止的循环,要求用户继续取消,同时显示实际的计数器状态(这是为了防止 Google 最大执行时间限制出现问题)。

它工作得很好,但在这个简化的测试脚本中,我用来测试它只工作一次的想法:当第一次“超时”发生时,它会按预期显示继续/取消选项,然后从开始的地方继续,但当第二次发生相同的情况时,继续按钮不会显示。

我的问题很简单:为什么?或者更好:两种情况有什么区别?

嵌入脚本的电子表格是 publicly testable here (参见菜单:测试)

整个脚本如下所示(当然有点长,但有趣的部分即将结束)

我使用 ScriptProperties 来跟踪执行时间并从离开的位置继续循环。

function onOpen() {   
var ss = SpreadsheetApp.getActiveSpreadsheet();
var menuEntries = [
{name: "test", functionName: "test"},
];
ss.addMenu("test", menuEntries);
}

function test(){
ScriptProperties.setProperty('restorePointers',[0,0].join('@'))
var app = UiApp.createApplication().setTitle("test");
app.setHeight(150).setWidth(250);
var doc = SpreadsheetApp.getActiveSpreadsheet();
var panel = app.createVerticalPanel();
var handlerCancel = app.createServerHandler('canceltest');
var handlerContinue = app.createServerHandler('continuetest');
var contCHandler = app.createClientHandler();
var cancel = app.createButton("cancel.", handlerCancel).setId('cancel').setVisible(false);
var cont = app.createButton('continue',handlerContinue).setId('continue').setVisible(false).addClickHandler(contCHandler);
var button = app.createButton('start').setId('button');
var handler = app.createServerClickHandler('runtest');
handler.addCallbackElement(panel);
contCHandler.forTargets(button).setEnabled(false).forEventSource().setVisible(false);
var cHandler = app.createClientHandler().forTargets(cancel).setVisible(true).forEventSource().setVisible(false);
button.addClickHandler(handler).addClickHandler(cHandler);
app.add(panel.add(button).add(cont).add(cancel))//.add(trig));
doc.show(app);
}

function canceltest(e){
var app = UiApp.getActiveApplication();
ScriptProperties.setProperty('restoreData','')
ScriptProperties.setProperty('restorePointers','canceled');
SpreadsheetApp.getActiveSpreadsheet().toast(' ','restore aborted');
app.close()
return app;
}

function continuetest(e){
runtest(e)
}

function runtest(e){
var dStart; var dEnd;
ScriptProperties.setProperty('startrestore',new Date().getTime().toString())
if(ScriptProperties.getProperty('restoreData')==null||Utilities.jsonStringify(ScriptProperties.getProperties()).indexOf('restoreData')==-1)
{ScriptProperties.setProperty('restoreData',Utilities.jsonStringify(e))
}
var app = UiApp.getActiveApplication();
var pointers = ScriptProperties.getProperty('restorePointers');
if(pointers=='0@0'){
dStart = 0;
dEnd = 500;
}else{
dStart = Number(pointers.split('@')[0]);
dEnd = Number(pointers.split('@')[1]);
}
// main loop --------------------------
for(var ee=dStart;ee<dEnd;++ee){ // main loop
var ccc = ScriptProperties.getProperty('restorePointers');
if(ccc=='canceled'){ app.close();return app};

Utilities.sleep(85); // simulate some activity


if((ee/10)==parseInt(ee/10)&&ee>0){
SpreadsheetApp.getActiveSpreadsheet().toast(ee+' steps completed')
if(new Date().getTime()-Number(ScriptProperties.getProperty('startrestore'))>12000){ ;// +- 12 sec timeout
ScriptProperties.setProperty('restorePointers',[ee,dEnd].join('@'));
app.getElementById('continue').setHTML('continue from '+ee).setVisible(true)
return app
}
}
}
// end of main loop-----------------
ScriptProperties.setProperty('restoreData','')
ScriptProperties.setProperty('restorePointers',0+'@'+0);
SpreadsheetApp.getActiveSpreadsheet().toast('normal process end');
app.close();
return app;
}

最佳答案

这就是阻止“继续”按钮随每个时间间隔更新的原因。您的服务器处理程序需要返回一个应用程序:

function continuetest(e){
return runtest(e) ///<<<
}

(ee/10)==parseInt(ee/10) 是一种每 10 个项目就评估 true 的尴尬方式。使用模数代替:

if((ee%10==0)&&ee>0){ ///<<< modulus

每次暂停后,ee 的值都会在 toast 中重复。可以通过记住最后显示的值并跳过它来解决此问题。

if (ee == Number(ScriptProperties.getProperty('lastToast'))) continue; ///<<< don't repeat toast
ScriptProperties.setProperty('lastToast',ee); ///<<<

完整脚本

function onOpen() {   
var ss = SpreadsheetApp.getActiveSpreadsheet();
var menuEntries = [
{name: "test", functionName: "test"},
];
ss.addMenu("test", menuEntries);
}

function test(){
ScriptProperties.setProperty('restorePointers',[0,0].join('@'))
var app = UiApp.createApplication().setTitle("test");
app.setHeight(150).setWidth(250);
var doc = SpreadsheetApp.getActiveSpreadsheet();
var panel = app.createVerticalPanel();
var handlerCancel = app.createServerHandler('canceltest');
var handlerContinue = app.createServerHandler('continuetest');
var contCHandler = app.createClientHandler();
var cancel = app.createButton("cancel.", handlerCancel).setId('cancel').setVisible(false);
var cont = app.createButton('continue',handlerContinue).setId('continue').setVisible(false).addClickHandler(contCHandler);
var start = app.createButton('start').setId('start');
var handler = app.createServerClickHandler('runtest');
handler.addCallbackElement(panel);
contCHandler.forTargets(start).setEnabled(false).forEventSource().setVisible(false);
var cHandler = app.createClientHandler().forTargets(cancel).setVisible(true).forEventSource().setVisible(false);
start.addClickHandler(handler).addClickHandler(cHandler);
app.add(panel.add(start).add(cont).add(cancel))//.add(trig));
doc.show(app);
}

function canceltest(e){
var app = UiApp.getActiveApplication();
ScriptProperties.setProperty('restoreData','')
ScriptProperties.setProperty('restorePointers','canceled');
SpreadsheetApp.getActiveSpreadsheet().toast(' ','restore aborted');
app.close()
return app;
}

function continuetest(e){
return runtest(e) ///<<<
}

function runtest(e){
var dStart; var dEnd;
ScriptProperties.setProperty('startrestore',new Date().getTime().toString())
if(ScriptProperties.getProperty('restoreData')==null||Utilities.jsonStringify(ScriptProperties.getProperties()).indexOf('restoreData')==-1)
{ScriptProperties.setProperty('restoreData',Utilities.jsonStringify(e))
}
var app = UiApp.getActiveApplication();
var pointers = ScriptProperties.getProperty('restorePointers');
if(pointers=='0@0'){
dStart = 0;
dEnd = 500;
}else{
dStart = Number(pointers.split('@')[0]);
dEnd = Number(pointers.split('@')[1]);
}
// main loop --------------------------
for(var ee=dStart;ee<dEnd;++ee){ // main loop
var ccc = ScriptProperties.getProperty('restorePointers');
if(ccc=='canceled'){ app.close();return app};

Utilities.sleep(85); // simulate some activity


if((ee%10==0)&&ee>0){ ///<<< modulus
if (ee == Number(ScriptProperties.getProperty('lastToast'))) continue; ///<<< don't repeat toast
ScriptProperties.setProperty('lastToast',ee); ///<<<
SpreadsheetApp.getActiveSpreadsheet().toast(ee+' steps completed')
if(new Date().getTime()-Number(ScriptProperties.getProperty('startrestore'))>12000) { // +- 12 sec timeout
ScriptProperties.setProperty('restorePointers',[ee,dEnd].join('@'));
app.getElementById('continue').setHTML('continue from '+ee).setVisible(true)
return app
}
}
}
// end of main loop-----------------
ScriptProperties.setProperty('restoreData','')
ScriptProperties.setProperty('restorePointers',0+'@'+0);
SpreadsheetApp.getActiveSpreadsheet().toast('normal process end');
app.close();
return app;
}

关于google-apps-script - 具有超时保护的循环仅运行一次 "as it should",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16548123/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com