[英]What happens when I “sleep” in GAS ? (execution time limit workaround)
在這背后(不是我承認......)有趣的問題是關於我使用的解決方法的真正問題,而沒有真正理解它是如何工作的。
首先簡要介紹一下我的用例,這一切都發生在側邊欄中顯示的文檔綁定UiApp中:
我必須在用GAS編寫的郵件合並應用程序中通過電子郵件創建和發送幾百個文檔。 當然,在沒有達到5分鍾執行時間限制的情況下,在一個批處理中花費太長時間,所以我嘗試了幾個不同的解決方法來完成任務:
它工作得很好,我處理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
}
服務器處理程序函數調用的語句不是獨立進程,因為它們“是從函數本身內部創建的”並不完全正確。
您已經使用服務器處理程序doSomething
設置了一個checkBox元素chk1
。 每當選中checkBox時,都會將一個事件分派給服務器。 (...並且您的腳本在每次chk1.setValue()
調用時都會導致這些事件) checkBox
和周圍的UI代碼在您的瀏覽器中運行 - 單擊“顯示源”或使用資源管理器查看chk1.setValue()
瀏覽器提供的內容谷歌服務器。 (警告 - 它被混淆了。但你可能會認識到你的一些字符串,以及你的客戶端代碼。)
以下是我們在Class ServerHandler的文檔中所說的內容 :
當調用ServerHandler時,它引用的函數在Apps腳本服務器上以“新鮮”腳本調用。
這是延長操作時間的關鍵:每個調度事件都會導致在全新的操作上下文中調用doSomething()
- 就像您在其他瀏覽器中打開腳本編輯器一樣,並在腳本上單擊“運行”。 “新鮮”腳本無法訪問以前運行的var值...但它也有自己的一組操作限制,包括計時器。
PS:您應該通過使用Lock確保服務器端處理程序是“線程安全的”,因為您正在訪問可由多個doSomething()
回調實例訪問的共享資源。 與此相關,可以使用此腳本達到另一個限制:
為了好玩,我在chk1
上注釋了.setVisible(false)
,因此checkBox是可見的。 然后我快速點擊了幾十次。 時間顯示無序運行,最終出現上述錯誤。 (幾分鍾后)當然,這是一個人為的情況,但仍然是一個容易避免的錯誤狀態。
PPS:我想知道是否可以使用相同的技術來分派多個並行服務器端處理程序,從而減少完成整個作業所用的時間?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.