元コードに手を加えず処理を追加。アスペクトを使ってみよう
通常、デバッグを行う際には既存のコードのあちこちにデバッグログを差し込んだりします。それでは修正が終わった後にクリーンなコードに戻すのも大変ですし、必要な部分を消してしまって余計なバグを作ることにもなりかねません。
そこで使ってみたいのがアスペクト(AOP)という仕組みです。hifiveではコントローラとロジックに対してアスペクトが適用できるようになっています。

デモ
例えば次のようなHTMLがあります。
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta charset="UTF-8">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Cache-Control" content="no-cache">
<meta http-equiv="Expires" content="-1">
<link rel="stylesheet" href="h5.css">
<script src="jquery.js"></script>
<script src="ejs-h5mod.js"></script>
<!-- 各モジュールのソースJSを読み込む -->
<script src="h5.js"></script>
<!-- ここで作成したjsファイルを読み込む -->
<script src="step13-1.js"></script>
<title>hifive Aspectの適用</title>
</head>
<body>
<div id="container">
<input type="button" id="btn" value="hello world!">
</div>
</body>
</html>
コントローラは step13–1.js になります。
// step13-1.js
$(function() {
var helloWorldController = {
__name: 'HelloWorldController',
'#btn click': function() {
alert('Hello, World!');
}
};
// id="container"である要素にコントローラをバインド
h5.core.controller('#container', helloWorldController);
});
このコードを見て分かる通り、#btnのクリックイベントに対してアラートを出しているのみです。ここにアスペクトを適用します。コードは h5preinit.js です。
<!-- hifiveのpreinitイベントで処理をさせるために、h5.jsより先に読み込む -->
<script src="h5preinit.js"></script> <!-- ← 追加します -->
<!-- 各モジュールのソースJSを読み込む -->
<script src="../../archives/current/h5.js"></script>
h5preinit.jsの内容は次のようになります。
// h5preinit.js
$(document).bind('h5preinit', function() {
// Loggerのレベルの設定
h5.settings.log = {
defaultOut: {
level: 'trace',
targets: 'console'
}
};
var aspect = {
target: 'HelloWorldController',
interceptors: h5.core.interceptor.lapInterceptor,
pointCut: '#btn click'
};
h5.settings.aspects = aspect;
});
aspectというオブジェクトはコントローラ、補足するイベントに加えてインターセプターを定義しています。h5.core.interceptor.lapInterceptorは処理の開始と終了時間を出力します。コードは次のようになります。
var lapInterceptor = h5.u.createInterceptor(function(invocation, data) {
// 開始時間をdataオブジェクトに格納
data.start = new Date();
// invocationを実行
return invocation.proceed();
}, function(invocation, data) {
// 終了時間を取得
var end = new Date();
// ログ出力
this.log.info('{0} "{1}": {2}ms', this.__name, invocation.funcName, (end - data.start));
});
createInterceptorはインターセプト先関数の実行前と、後に実行される関数を定義します。inovocationという変数は以下のプロパティを持ちます。
- target
- インターセプト対象の関数が属しているコントローラまたはロジック
- func
- インターセプト対象の関数
- funcName
- インターセプト対象の関数名
- args
- 関数が呼ばれたときに渡された引数(argumentsオブジェクト)
- proceed
- インターセプト対象の関数を実行する関数。インターセプト対象の関数は自動では実行されません。 インターセプト先の関数を実行するには、 preに指定した関数内でinvocation.proceed()を呼んでください。 proceed()を呼ぶと対象の関数(invocation.func)を呼び出し時の引数(invocation.args)で実行します。 proceed自体は引数を取りません。
実際に実行するとDevToolsのコンソールに次のように出力されます。
[INFO]19:55:11,641: HelloWorldController.#btn clickが開始されました。
[INFO]19:55:11,646: Arguments[2]
[INFO]19:55:13,168: HelloWorldController.#btn clickが終了しました。 Time=1517ms
このようにして関数の実行前と後をチェックできるようになります。インターセプターは自作できますので、実際に稼働しているコードを編集することなくデバッグ作業を効率的に行えるようになります。
今回のコードはhifive Aspectの適用にて試すことができます。コンソールを開いてその出力結果をご覧ください。
コメントは受け付けていません。