Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-apps-script/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Google apps script 带超时保护的循环,只运行一次;正如它应该的那样;_Google Apps Script - Fatal编程技术网

Google apps script 带超时保护的循环,只运行一次;正如它应该的那样;

Google apps script 带超时保护的循环,只运行一次;正如它应该的那样;,google-apps-script,Google Apps Script,我编写了一个脚本,可以从电子表格中的备份中恢复日历数据。由于数据量高度不可预测,我设计了一个循环,在给定的分钟数后停止,要求用户在显示实际计数器状态时继续或取消(这是为了防止Google max execution time limit出现问题) 它工作得很好,但在我用来测试这个想法的简化测试脚本中,它只工作一次:当第一个“超时”发生时,它按预期显示continue/cancel选项,然后从开始的位置继续,但是当第二次出现相同情况时,continue按钮不显示 我的问题很简单:为什么?或者更好:

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

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

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

嵌入脚本的电子表格是(请参见
菜单:测试

整个脚本如下图所示(当然有点长,但interesting部分已接近尾声)

我使用
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;  
} 
函数onOpen(){
var ss=SpreadsheetApp.getActiveSpreadsheet();
变量菜单项=[
{name:“test”,functionName:“test”},
];  
ss.添加菜单(“测试”,菜单);
}
功能测试(){
ScriptProperties.setProperty('restorePointers',[0,0]。连接('@'))
var app=UiApp.createApplication().setTitle(“测试”);
安装高度(150)、安装宽度(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(面板);
contCHandler.forTargets(按钮).setEnabled(错误).forEventSource().setVisible(错误);
var cHandler=app.createClientHandler().forTargets(取消).setVisible(真).forEventSource().setVisible(假);
addClickHandler(handler).addClickHandler(cHandler);
app.add(面板添加(按钮).add(继续).add(取消))/.add(触发));
文件显示(应用程序);
}
功能测试(e){
var app=UiApp.getActiveApplication();
ScriptProperties.setProperty('restoreData','')
setProperty('restorePointers','cancelled');
SpreadsheetApp.getActiveSpreadsheet().toast(“”,'restore aborted');
app.close()
返回应用程序;
}  
函数连续测试(e){
运行测试(e)
}
函数运行测试(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');
如果(指针=='0@0'){
dStart=0;
dEnd=500;
}否则{
dStart=Number(指针.split('@')[0]);
dEnd=编号(指针.split('@')[1]);
}
//主回路--------------------------
对于(var ee=dStart;ee0){
SpreadsheetApp.getActiveSpreadsheet().toast(ee+“步骤完成”)
如果(new Date().getTime()-Number(ScriptProperties.getProperty('startrestore'))>12000){;//+-12秒超时
ScriptProperties.setProperty('restorePointers',[ee,dEnd].join('@');
app.getElementById('continue').setHTML('continue from'+ee.).setVisible(true)
返回应用程序
}
}
}
//主回路结束------------------
ScriptProperties.setProperty('restoreData','')
setproperties('restorePointers',0+'@'+0);
SpreadsheetApp.getActiveSpreadsheet().toast('正常进程结束');
app.close();
返回应用程序;
} 

以下是阻止“继续”按钮每次更新的原因。您的服务器处理程序需要返回一个应用程序:

function continuetest(e){
  return runtest(e)  ///<<<
}
每次暂停后,ee的值都会在toast中重复。这可以通过记住最后显示的值并跳过它来修复

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

如果(ee==Number(ScriptProperties.getProperty('lastToast'))继续///我遇到了一个类似的事件,虽然我的函数与按钮完全相关,但函数只触发一次。我希望我们能尽快解决。我怀疑这与return应用程序杀死最初设置的任何处理程序有关。像往常一样,很好的答案:-)没有考虑从continue返回函数本身。。。也谢谢你的想法。这可能是我的“业余”JS编程方法的症状,我除了自己尝试/实验之外从未学过任何东西,所以你的答案给了我学习更好、更“学术”的机会。谢谢。我玩得很开心,也从中学到了很多。我自己也没做过那么多。
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;  
}