在这背后(我承认不是那么多......)有趣的问题是一个关于我使用的解决方法的真正问题,但没有真正理解它是如何工作的。
首先简要描述我的用例,所有这一切都发生在侧边栏中显示的文档绑定 UiApp 中:
我必须在用 GAS 编写的邮件合并应用程序中创建并通过电子邮件发送数百个文档。当然,在不达到 5 分钟执行时间限制的情况下进行一批处理需要太长时间,因此我尝试了几种不同的解决方法来完成任务:
- 当我启动进程时,以及当我达到接近限制的预定义值时,我使用时间戳(存储在 ScriptProperties 中),我存储当前值(指针、有用的变量...)并返回到用户界面,要求用户继续(或不)。这工作得很好,但需要人工操作才能完成整个任务。
- 因此,我使用在第一个处理程序调用中创建的计时器触发器设置了一个解决方案,并且该触发器调用文档创建/发送函数。这也工作得很好,但触发器调用的函数无法与 UI 交互,因为似乎只有处理程序函数可以更新 UI。问题是我无法显示进度,也无法轻松显示进程何时结束。
- 然后我想起了不久前为了好玩而写的一个小应用程序:它是一个计时器,使用复选框作为服务器处理程序触发器(来自 Romain Vialard 很久以前在旧 Google 论坛上提出的想法),并决定尝试这个我的邮件发送过程中的诡计。
它工作得很好,每次调用我都会处理 40 个文档批次(大约 3 分钟),然后暂停一段时间,然后重新开始,直到完成。
每个调用都由 checkBox 链接的服务器处理程序触发,复选框本身在处理程序函数中发生更改,以这种方式创建自己的触发器。
我的问题(最后;-)是:知道整个过程可能需要 30 到 60 分钟,这可能有多精确?这些服务器处理程序函数如何/为什么被视为多进程,因为它们是从函数本身内部创建的?
我希望我足够清楚,(我对此表示怀疑,因为我的头脑有点混乱:-)
我在下面加入了时钟测试应用程序的代码,它给了我这个想法,它可能会让事情更容易理解。
function doGet() {
var app = UiApp.createApplication().setTitle('Counter/Timer');
var Panel = app.createAbsolutePanel().setStyleAttribute('padding','35');
var counter = app.createHTML().setId('counter').setHTML('<B>Timer = wait</B>').setStyleAttribute('fontSize','40px');// set start display
var clo = app.createTextBox().setName('clo').setId('clo').setValue('0').setVisible(false);//set start value in seconds
var handler1 = app.createServerHandler('doSomething').addCallbackElement(Panel);
var chk1 = app.createCheckBox('test1').addValueChangeHandler(handler1).setVisible(true).setId('chk1').setVisible(false);
app.add(Panel.add(chk1).add(counter).add(clo));
chk1.setValue(true,true);// start the process
return app}
function doSomething(e) {
var app = UiApp.getActiveApplication();
var xx = Number(e.parameter.clo);
var disp = app.getElementById('counter')
xx++ ;// replace by xx-- to count downwards
if(xx>600){ // 10 minutes timeout for example
disp.setHTML('<B> GAME OVER ;-)</B>').setStyleAttribute('fontSize','80px').setStyleAttribute('color','RED')
return app
}
var cnt = app.getElementById('clo').setValue(xx)
disp.setHTML('<B>'+T(xx)+'</B>')
Utilities.sleep(1000); // instead of sleeping do something !
// below comes the "active" part
var chk1 = app.getElementById('chk1').setValue(false,false)
var chk1 = app.getElementById('chk1').setValue(true,true)
return app;
}
function T(val){
var min = parseInt(val/60);
var sec = val-(60*min);
if(sec<10){sec='0'+sec}
if(min<10){min='0'+min}
var st = '> '+min+':'+sec
return st
}