domainのおさらい
非同期処理を行う際にdomainと紐付けておくと、domain単位でエラーハンドリングでき、さらにそのdomainに紐付けられた非同期処理の中から呼び出された非同期処理も、同じdomainに紐付きます。
var Domain = require("domain");
//エラーハンドラ
var handler = function(e){
console.log(e);
};
//TEST
var test = function(code, wait){
var d = Domain.create();
d.on("error", handler);
d.run(function(){
setTimeout(function(){
setTimeout(function(){
setTimeout(function(){
//非同期で例外をスロー
throw new Error(code);
}, wait);
}, wait);
}, wait);
});
};
test(1, 40);
test(2, 140);
test(3, 70);
//1,3,2の順番にhandler関数が呼ばれる
パラメータを渡して業務処理を行うとすると、以下のようなコードになります。
var Domain = require("domain");
//業務処理
var work = function(code){
console.log(code);
};
//TEST
var test = function(code, wait){
var d = Domain.create();
d.run(function(){
setTimeout(function(){
setTimeout(function(){
//業務処理の呼び出し
work(code);
}, wait);
}, wait);
});
};
test(1, 40);
test(2, 140);
test(3, 70);
//1,3,2の順番で業務処理が呼び出される
domainに値を設定
もし何らかの事情でwork関数は非同期呼び出ししかできず、さらにパラメータを渡すのも難しい場合、domainに値を追加するという方法があります。
var Domain = require("domain");
//業務処理
var work = function(){
//process.domainは現在の実行domainがセットされている
console.log(process.domain.code);
};
//TEST
var test = function(code, wait){
var d = Domain.create();
//値を追加する。domainオブジェクトの関数上書きに注意
d.code = code;
d.run(function(){
setTimeout(function(){
//業務処理の呼び出し
setTimeout(work, wait);
}, wait);
});
};
test(1, 40);
test(2, 140);
test(3, 70);
このコードでは作成したdomainのcodeに値をセットし、process.domain.codeから値を参照しています。
globalを使ってグローバル変数のように参照
ここからがトリックになります。globalにgetterを設定し、そのgetterでprocess.domain.codeを返すようにすると、グローバル変数のように扱えます。
var Domain = require("domain");
//業務処理
var work = function(){
//globalのメンバーは直接参照可能
console.log(code);
};
//globalオブジェクトにプロパティを設定
Object.defineProperty(global, "code", {
get : function(){
//ここで現在の実行ドメインを返す
return process.domain.code;
}
});
//TEST
var test = function(code, wait){
var d = Domain.create();
d.code = code;
d.run(function(){
setTimeout(function(){
setTimeout(function(){
setTimeout(work, wait);
}, wait);
}, wait);
});
};
test(1, 40);
test(2, 140);
test(3, 70);
globalを使用するのはトリッキーではありますが、DSLを作成する際などに便利かと思います。