11

この背後にある (あまり認めない...) 面白い質問は、私が実際にどのように機能するかを理解せずに使用する回避策についての実際の質問です。

最初に私の使用例の簡単な説明です。これはすべて、サイドバーに表示されるドキュメントにバインドされた UiApp で行われています。

GAS で書かれた差し込み印刷アプリケーションで数百の文書を作成して電子メールで送信する必要があります。もちろん、5 分の実行時間制限に達することなく 1 つのバッチで処理するには時間がかかりすぎるため、タスクを完了するためにいくつかの異なる回避策を試しました。

  1. プロセスを開始するときにタイム スタンプ (ScriptProperties に格納されている) を使用し、制限に近い事前定義された値に達すると、現在の値 (ポインター、便利な変数...) を格納し、ユーザー インターフェイスに戻ってユーザーに続行するように求めます (か否か)。これはかなりうまく機能しますが、タスク全体を完了するには人間の行動が必要です。
  2. そこで、最初のハンドラー呼び出しで作成したタイマー トリガーを使用してソリューションをセットアップし、このトリガーがドキュメント作成/送信関数を呼び出します。これもうまく機能していますが、UI を更新できるのはハンドラー関数のみであるように見えるため、関数と呼ばれるトリガーは UI とやり取りできません。問題は、進行状況を表示したり、プロセスがいつ終了したかを簡単に表示したりできないことです。
  3. それから、ちょっと前に楽しみのために書いた小さなアプリを思い出しました。それはサーバー ハンドラー トリガーとして checkBox を使用するタイマーでした (古い Google フォーラムで Romain Vialard によってずっと前に提案されたアイデアから)、これを試すことにしました。私のメール送信プロセスのトリック。

それは完全に機能します。私は 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
}

ここに画像の説明を入力

4

1 に答える 1

10

サーバーハンドラー関数が呼び出すステートメントは、「関数自体の内部から作成される」ため、独立したプロセスではありません。

chk1サーバー ハンドラを使用して checkBox 要素を設定しましたdoSomething。checkBox がチェックされるたびに、イベントがサーバーにディスパッチされます。chk1.setValue()(...そして、スクリプトはすべての呼び出しでこれらのイベントを引き起こしています)checkBoxおよび周囲の UI コードはブラウザーで実行されています。[ソースを表示] をクリックするか、エクスプローラーを使用して、Google サーバーによってブラウザーに提供されたものを確認します。(警告 - 難読化されています。ただし、一部の文字列と、そこからクライアント側のコードを認識できる場合があります。)

Class ServerHandlerのドキュメントで説明されていることは次のとおりです。

ServerHandler が呼び出されると、それが参照する関数が Apps Script サーバー上で「新しい」スクリプトで呼び出されます。

これは、操作時間を延長するための鍵です。ディスパッチされた各イベントによりdoSomething()、まったく新しい操作コンテキストが呼び出されます。別のブラウザーでスクリプト エディターを開いて、スクリプトの [実行] をクリックしたようなものです。「新鮮な」スクリプトは、以前の実行の var 値にアクセスできません...しかし、タイマーを含む独自の一連の操作制限も与えられます。

PS: コールバックの複数のインスタンスによってアクセスされる可能性のある共有リソースにアクセスしているため、Lock を使用してサーバー側ハンドラーが「スレッド セーフ」であることを確認する必要がありdoSomething()ます。それに関連して、次のスクリプトで別の制限に達する可能性があります。

スクリーンショット - エラー

ふざけて、 をコメントアウトし.setVisible(false)chk1、checkBox が表示されるようにしました。それから数十回すばやくクリックしました。時刻表示がおかしくなり、最終的に上記のエラーが表示されました。(数分後) もちろん、これは人為的な状況ですが、それでも簡単に回避できるエラー状態です。

PPS: 複数の並列サーバー側ハンドラーをディスパッチするために同じ手法を使用して、ジョブ全体を完了するまでの経過時間を短縮できるのではないでしょうか?

于 2013-06-03T00:53:58.413 に答える