2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

OutSystems で JavaScript ポーリングによるバックグラウンド処理進捗表示を実装する

Posted at

はじめに

Web 画面からのアクションでタイマーをスタートし、バックグラウンドでタスク処理を実行する要件を検討する機会がありました。
その際フロントの操作が行える状態のまま、画面更新をせず、非同期に処理の進捗状況を追えるか?といった課題があったので、仮実装を行い JavaScript にてフロント → サーバーのポーリングを行えるか調査しました。

※他にも Forge などの方法もありそうですが、今回は JavaScript のみ言及します。

本実装は基本的なポーリング機能のサンプルとなります。
本格的なプロダクション環境での利用を検討される場合は、
要件にあわせポーリング間隔の最適化や、エラーハンドリングなど追加の実装・検討が必要です。

つくるもの

  • 画面からのアクションで数分かかるタイマーをスタートして、バックグランドとして処理する
  • タイマーの処理全体は排他処理のため Batch というテーブルで 1 レコード=1 タイマーとして実行中のものが 1 レコードになるよう管理する
  • タイマー内各タスクの状態は、BatchTaskQueue  という子テーブルにいれ、1 タスク= 1 レコードとして順番に処理していく
  • バックグラウンド処理は数分かかる想定なので、その間もフロントのユーザーの操作を邪魔しないようにする

できたもの

ボタンを押下する。
image.png

バッチ処理が開始される。
image.png

再度ボタンを押下した場合は、実行中であるため開始されない
image.png

別タブにて、再度ボタンを押下した場合も、実行中であるため開始されない
Items.png

しばらくするとプログレスバーが進む。
image.png

さらに進んでプログレスバーが完了になる。
image.png

作成手順

テーブルを作成する

BatchBatchTaskQueue
image.png

タイマーおよびタイマー処理のサーバーアクションを作成する

アクション名: Batch/Execute

  1. IsProcessing = TrueBatch を取得する
  2. 該当 Batch に紐づく IsCompleted = FalseBatchTaskQueue を取得する
  3. 取得した BatchTaskQueue でループする
  4. ループ内で、なんらか時間のかかる処理をする(今回は Forge の Sleep で代用)
  5. ループ内で、Batch.CompletedTaskCount をインクリメントし、かつ BatchTaskQueue.IsCompleted = True に更新する
  6. ループ後、Batch.IsProcessing = FalseBatch.IsCompleted = True に更新する

image.png

バッチが実行されているかどうかを取得するサーバーアクションを作成する

アクション名: IsBatchProcessing

  1. IsProcessing = TrueBatch 有無で True/False を返す

任意のタスクをつくり、タイマーを起動するサーバーアクションを作成する

アクション名: CreateBatchWithTasks

  1. IsBatchProcessingFalse の場合に処理を開始する

  2. Batch に 1 レコード作成する

    • IsProcessing: True
  3. 2.の Batch に紐づく BatchTaskQueue を 3 レコード固定でデータ作成する

    • IsCompleted: False
  4. 作成に成功した場合はタイマーを起動し、IsCreated = True を返す
    IsBatchProcessing = Falseの場合は、IsCreated = False を返す。

タイマーの進行状況を取得するサーバーアクションを作成する

アクション名: GetBatchProgress

  1. IsProcessing = TrueBatch を取得する
  2. 以下を返す
    • TotalTaskCount: タスクの総数
    • CompletedTaskCount: 完了したタスクの数
    • ProgressPercent: 完了したタスクの数 / タスクの総数 * 100(パーセント)
      ※プログレスバーが 0 ~ 100 のため、小数ではなくパーセントで計算する。

image.png

画面を追加し、ローカル変数を用意する

  • IsLoading: ボタンローディング用(Boolean)
  • Progress: プログレスバー用(Integer)

ボタン、プログレスバーを画面に追加する

image.png

OnReady を追加する

  1. IsBatchProcessingTrue の場合に処理を開始する
  2. JavaScript で以下を実装する
    SetInterval:
if (!window.pollingTimer) {
  window.pollingTimer = setInterval(function () {
    $actions.PollBatchProgress();
  }, 5000);
}

image.png

ボタン押下時のクライアントアクションを作成する

アクション名: ButtonOnClick

  1. ローディングを開始する
  2. CreateBatchWithTasks を呼び出して、タスクを作成する
  3. IsCreated = True (タイマーが実行中ではない)の場合は OnReady 同様 JavaScript で SetInterval を呼び出す
  4. ローディングを終了する

image.png

サーバーをポーリングするクライアントアクションを作成する

アクション名: PollBatchProgress

  1. GetBatchProgress でバッチの処理状況を取得する
  2. GetBatchProgress.ProgressPercent をローカル変数の Progress にセットする(プログレスバーの更新)
  3. GetBatchProgress.ProgressPercent = 100 (タイマーの実行が完了)の場合は JavaScript で ClearInterval を呼び出す

ClearInterval:

if (window.pollingTimer) {
  clearInterval(window.pollingTimer);
  window.pollingTimer = null;
}

image.png

OnDestroy を追加する

同様に OnDestroy にも ClearInterval を追加します。

以上

2
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?