Table of Contents

イベント

概要

BitsmistJSの特徴のひとつが、イベントドリブンです。各ユニットでは様々なタイミングでイベントが発生します。イベントが発生するとBitmistJSが引数を準備し、登録されているイベントハンドラを呼び出します。各イベントに対するイベントハンドラ内に処理を記述することで、ユニットの動作を作成していきます。

ここではイベントについて説明します。

イベントの種類

発生するイベントには、“click”イベントのようなJavascriptネイティブのイベントと、“doSetup”のようなBitsmistJSの独自のイベントがあります。

独自イベントはJavascript標準のカスタムイベントを使って実装されています。そのため多くの場合、JavascriptネイティブなのかBitmistJSオリジナルなのかを意識せずに使えるようになっています。

BitsmistJSオリジナルイベント

ここではコアライブラリが発生させるイベントの一覧を紹介します。BitsmistJSイベントは1つのイベントに対し、before/do/afterで始まるイベントの3セットになっています(そうでないものもありますが)。doで始まるイベントでメインとなる処理を行い、before/afterで始まるイベントでは、その前処理/後処理を行います。

イベント説明
beforeStart初期化時の処理を行います。
doStart
afterStart
beforeStop終了時の処理を行います。
doStop
afterStop
beforeApplySettings設定を適用する処理を行います。
doApplySettings
afterApplySettings
beforeSetupユニットに設定を反映する処理を行います。
doSetup
afterSetup
beforeTransformHTMLテンプレート追加時の処理を行います。
doTransform
afterTransform
beforeRefresh画面描画時の処理を行います。
doRefresh
afterRefresh
beforeFetchデータ取得時の処理を行います。
doFetch
afterFetch
beforeClearユニットをクリアする処理を行います。
doClear
afterClear
beforeFillユニットにコンテンツを満たす処理を行います。
doFill
afterFill
afterReadyユニットの初期化終了後の処理を行います。

イベントハンドラの書き方

各イベントハンドラは共通の引数を持っています。Javascriptネイティブなイベント、BitsmistJSオリジナルなイベント、いずれもこのイベントハンドラの形式で対応します。

onDoSetup(sender, e, ex)
{
}

イベントハンドラには3つの引数があります。この3つの引数はBitsmistJSによってセットされます。

sender

senderにはこのイベントを発生させたオブジェクトが渡されます。例えば、クリックイベントの場合はクリックした要素、doSetupの場合はユニット自身が入っています。

e

Javascriptネイティブなイベントの場合、ここにはイベントリスナーに渡されるイベント情報がそのまま渡されます。例えばclickイベントの場合は、MouseEventオブジェクトが渡されます。BitmistJSオリジナルなイベントの場合は、イベントを発生させたユニットが渡すイベント情報が入ります。

ex

この引数には設定のイベントハンドラ情報の“options”で指定された内容が渡されます。

イベントハンドラの指定方法

どの要素のどのイベント時にどのイベントハンドラを使用するかを、設定の“event.events”セクションに記述します。

_getSettings()
{
    return {
        "event": {
            "events": {
                "this": {
                    "handlers": {
                        "doSetup": this.onDoSetup
                    }
                },
                "btn-menu": {
                    "handlers": {
                        "click": this.onBtnMenu_Click
                    }
                }
            }
        }
    }
}

この例では“this”(ユニット自身)のdoSetupイベントでonDoSetup()メソッドを呼び出すように指定しています。またメニューボタンがクリックされた際には、onBtnMenu_Click()メソッドを呼び出すようにも指定しています。

要素の指定の仕方、ハンドラの指定の仕方など、詳細はイベントパークのリファレンスをご覧ください。

イベントハンドラの順番

同じ要素の同じイベントに複数のイベントハンドラがある場合、基本的には登録された順番に実行されます。

_getSettings()
{
    return {
        "event": {
            "events": {
                "this": {
                    "handlers": {
                        "doSetup": [
                            {
                                "handler": this.onDoSetup1
                            },
                            {
                                "handler": this.onDoSetup2,
                            }
                        ]
                    }
                }
            }
        }
    }
}

上記の場合、this.onDoSetup1()→this.onDoSetup2()の順に実行されます。

ハンドラ情報の“order”に数値を指定すると、この順番を制御することができます。より高い数値のイベントハンドラが先に実行されます。指定がない場合は0となります。

_getSettings()
{
    return {
        "event": {
            "events": {
                "this": {
                    "handlers": {
                        "doSetup": [
                            {
                                "handler": this.onDoSetup1
                            },
                            {
                                "handler": this.onDoSetup2,
                                "order": 10
                            }
                        ]
                    }
                }
            }
        }
    }
}

上記の場合は、this.onDoSetup2()→this.onDoSetup1()の順になります。

イベントハンドラの実行を同期する

各イベントハンドラは非同期で実行されます。Promiseを返し適切なタイミングでresolve/rejectすることで、次の処理はこのイベントハンドラの終了を“待つ”ようになります。

onDoSetup1(sender, e, ex)
{
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log("setup1");
            resolve();
        }, 2000);
    });
}
 
onDoSetup2(sender, e, ex)
{
    console.log("setup2");
}

上記の2つのイベントハンドラがユニットのdoSetupイベントに登録されていた場合、

setup1
setup2

と順番に表示されます。もしPromiseを返さない場合はどうなるでしょうか?

onDoSetup1(sender, e, ex)
{
    setTimeout(() => {
        console.log("setup1");
    }, 2000);
}
 
onDoSetup2(sender, e, ex)
{
    console.log("setup2");
}
setup2
setup1

setup2が先に表示されます。

これは同じイベントに複数のイベントハンドラが存在する場合の例でしたが、違うイベントが続けて発生する場合も同じことが言えます。例えばユニットの“basic.setup”スペルを呼び出すと、beforeSetup→doSetup→afterSetupという流れでイベントが発生します。beforeSetupのイベントハンドラでPromiseを返さない場合は、beforeSetupの処理の終了を待たずに、doSetupの処理が走ります。後続の処理が待つ必要がある場合は、常にPromiseを返し、適切なタイミングでresolve/rejectしてください。