2013年9月26日

JavaScriptでタスクをスケジュール実行する

 あるシステムで任意のタスクをスケジュールされた時刻になったら、自動的に実行するという要件がありまして、それをJavaScriptで実現するためのクラスを作ってみました。
 タスクの終了関係なしに、時間が来たら次のタスクが実行されます。
 もともと、Javaでやっていたものの移植になります。

ファイルの説明

  • index.html
    ジョブを実行するサンプルのhtmlです。
  • main.js
    ジョブを実行するサンプルのJavaScriptです。
  • scheduler.js
    ジョブのスケジューリングを行うメインのJavaScriptです。
    TaskerとSchedulerという2つのオブジェクトがあります。
    Taskerは、主にタスクのスケジューリング管理とタスクの実行を行います。
    Schedulerは、スケジュールデータのタスクデータを管理します。


用途
 テレビのように時間が来たら番組が変わるように、時刻をきっかけに動画の再生を強制的に切り替えるようなアプリケーションなどに使えると思います。
 実行中のタスクを無視して次のタスクを実行するというような要件がどれくらいあるかわかりませんが…。

使い方の解説
 最低限やることは、3つだけです。

  1. タスクデータの準備
    タスクを連想配列として定義し、配列として準備します。
    タスクのデータ構造は、自由に定義してもよいですが、タスクの実行開始時刻を計算できる項目を持たせる必要があります。
    TaskerのgetIntervalTimeでタスクを実行する前のIntervalTime(待ち時間)を計算するためです。
  2. SchedulerとTaskerのインスタンスの準備と、Taskerの一部関数の書き換え(Override的な)です。
    TaserのインスタンスのuserProcessとgetIntervalTime関数を書き換えます。
    userProcess関数は、タスクを実行する関数の内容を記述します。引数として、タスクデータを受け取ります(サンプルでは、タスクデータのmsgキーの値をコンソールに表示しています)。
    getIntervalTime関数は、受け取ったタスクデータを実行するまでの時間を秒で返却します(サンプルでは、現在時刻とタスクデータの時刻の差を算出し、秒にして返却しています)。
    他にも、startJob、endJobという関数があります。それぞれ、ジョブの開始時と終了時に呼び出されます。
  3. 上記準備ができたら、実行します。
    SchedulerのインスタンスをTaskerにコンストラクタに渡してインスタンスを生成し、実行します。
    実行するためには、Taskerオブジェクトのexecuteメソッドを使用します。
    executeメソッドは、bool型の引数を一つ持っています。
    true..既に開始時刻を経過しているタスクを即実行し、次のタスクをスケジュールする。
    false(または、未指定)..既に開始時刻を経過しているタスクは実行せずに、次のタスクをスケジュールする。

    コーディング例)
    var data = [
                {time: "100000", msg: "タスク1"},
                {time: "100100", msg: "タスク2"}
               ];
    var sch_data = new Scheduler(data);
    var task = new Tasker(sch_data);
    task.execute(false);
    

Download

おすすめ図書

3 件のコメント:

  1. こちらのサンプルソースコードが動かないです。

    返信削除
    返信
    1. どこかでエラーが出てませんか?

      削除
  2. dataの一番目のtimeが未来の時間の場合、一番目のタスクが実行されない。
    下記のように修正したら、ちゃんと実行されるようになったよ。ご参考まで

    /**
    1番目のタスクの実行と次のスケジューリング
    */
    Tasker.prototype.scheduleTask = function(firstTaskExecute) {
    var sch_data = this.scheduler.read();

    // スケジュールすべきデータか判定する
    while(sch_data!==null && !this.useSchedule(sch_data)) {
    sch_data = this.scheduler.read();
    }

    if(sch_data!==null) {
    // 1番目のタスクを実行する
    var me = this;

    if(firstTaskExecute) {
    if(this.isStarted(sch_data)) {
    // 最初のタスクを実行する
    setTimeout(function() {
    me.userProcess(sch_data);
    }, 0);
    } else {
    var interval = this.getIntervalTime(sch_data) * 1000;
    // 最初のタスクを実行する
    setTimeout(function() {
    me.userProcess(sch_data);
    }, interval);
    }
    }
    // 次のタスクのスケジュール
    this.rescheduleTask();
    } else {
    // 全てのスケジュールを読み終わった
    this.endJob();
    this.cancel();
    }
    }

    返信削除