はじめに
Web 画面からのアクションでタイマーをスタートし、バックグラウンドでタスク処理を実行する要件を検討する機会がありました。
その際フロントの操作が行える状態のまま、画面更新をせず、非同期に処理の進捗状況を追えるか?といった課題があったので、仮実装を行い JavaScript にてフロント → サーバーのポーリングを行えるか調査しました。
※他にも Forge などの方法もありそうですが、今回は JavaScript のみ言及します。
本実装は基本的なポーリング機能のサンプルとなります。
本格的なプロダクション環境での利用を検討される場合は、
要件にあわせポーリング間隔の最適化や、エラーハンドリングなど追加の実装・検討が必要です。
つくるもの
- 画面からのアクションで数分かかるタイマーをスタートして、バックグランドとして処理する
- タイマーの処理全体は排他処理のため
Batchというテーブルで 1 レコード=1 タイマーとして実行中のものが 1 レコードになるよう管理する - タイマー内各タスクの状態は、
BatchTaskQueueという子テーブルにいれ、1 タスク= 1 レコードとして順番に処理していく - バックグラウンド処理は数分かかる想定なので、その間もフロントのユーザーの操作を邪魔しないようにする
できたもの
別タブにて、再度ボタンを押下した場合も、実行中であるため開始されない。

作成手順
テーブルを作成する
タイマーおよびタイマー処理のサーバーアクションを作成する
アクション名: Batch/Execute
-
IsProcessing = TrueのBatchを取得する - 該当
Batchに紐づくIsCompleted = FalseのBatchTaskQueueを取得する - 取得した
BatchTaskQueueでループする - ループ内で、なんらか時間のかかる処理をする(今回は Forge の Sleep で代用)
- ループ内で、
Batch.CompletedTaskCountをインクリメントし、かつBatchTaskQueue.IsCompleted = Trueに更新する - ループ後、
Batch.IsProcessing = False、Batch.IsCompleted = Trueに更新する
バッチが実行されているかどうかを取得するサーバーアクションを作成する
アクション名: IsBatchProcessing
-
IsProcessing = TrueのBatch有無でTrue/Falseを返す
任意のタスクをつくり、タイマーを起動するサーバーアクションを作成する
アクション名: CreateBatchWithTasks
-
IsBatchProcessingがFalseの場合に処理を開始する -
Batchに 1 レコード作成する- IsProcessing: True
-
2.の
Batchに紐づくBatchTaskQueueを 3 レコード固定でデータ作成する- IsCompleted: False
-
作成に成功した場合はタイマーを起動し、
IsCreated = Trueを返す
※IsBatchProcessing = Falseの場合は、IsCreated = Falseを返す。
タイマーの進行状況を取得するサーバーアクションを作成する
アクション名: GetBatchProgress
-
IsProcessing = TrueのBatchを取得する - 以下を返す
- TotalTaskCount: タスクの総数
- CompletedTaskCount: 完了したタスクの数
- ProgressPercent: 完了したタスクの数 / タスクの総数 * 100(パーセント)
※プログレスバーが 0 ~ 100 のため、小数ではなくパーセントで計算する。
画面を追加し、ローカル変数を用意する
-
IsLoading: ボタンローディング用(Boolean) -
Progress: プログレスバー用(Integer)
ボタン、プログレスバーを画面に追加する
OnReady を追加する
-
IsBatchProcessingがTrueの場合に処理を開始する - JavaScript で以下を実装する
SetInterval:
if (!window.pollingTimer) {
window.pollingTimer = setInterval(function () {
$actions.PollBatchProgress();
}, 5000);
}
ボタン押下時のクライアントアクションを作成する
アクション名: ButtonOnClick
- ローディングを開始する
-
CreateBatchWithTasksを呼び出して、タスクを作成する -
IsCreated = True(タイマーが実行中ではない)の場合はOnReady同様 JavaScript でSetIntervalを呼び出す - ローディングを終了する
サーバーをポーリングするクライアントアクションを作成する
アクション名: PollBatchProgress
-
GetBatchProgressでバッチの処理状況を取得する -
GetBatchProgress.ProgressPercentをローカル変数のProgressにセットする(プログレスバーの更新) -
GetBatchProgress.ProgressPercent = 100(タイマーの実行が完了)の場合は JavaScript でClearIntervalを呼び出す
ClearInterval:
if (window.pollingTimer) {
clearInterval(window.pollingTimer);
window.pollingTimer = null;
}
OnDestroy を追加する
同様に OnDestroy にも ClearInterval を追加します。
以上











