google apps script - Loop with timeout protection that only runs once "as it should" -


i wrote script restores calendar data backup written in spreadsheet. since amount of data highly unpredictable designed loop stops after given number of minutes , asking user continue or cancel while showing actual counter state (this prevent issue google max execution time limit).

it works pretty in simplified test script used testing idea works once : when first "timeout" occurs, shows continue/cancel option expected , continues started when same condition happens second time continue button doesn't shows up.

my question : why ? or better : what's difference between both situations ?

the spreadsheet embedded script publicly testable here (see menu : test)

and whole script shown below (it's bit long of course interresting part near end)

i used scriptproperties keep track of execution time , continue loop left.

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 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 '+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;   }  

here's what's keeping 'continue' button updating each interval. server handler needs return app:

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

this bit, (ee/10)==parseint(ee/10) awkward way evaluate true every 10th item. use modulus instead:

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

after each pause, value of ee repeated in toast. can fixed remembering last displayed value was, , skipping it.

if (ee == number(scriptproperties.getproperty('lasttoast'))) continue; ///<<< don't repeat toast scriptproperties.setproperty('lasttoast',ee);  ///<<< 

full script

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 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 '+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;   }  

Comments

Popular posts from this blog

jquery - How can I dynamically add a browser tab? -

node.js - Getting the socket id,user id pair of a logged in user(s) -

keyboard - C++ GetAsyncKeyState alternative -