LoginSignup
0
0

More than 5 years have passed since last update.

非同期処理におけるglobalとdomainを使ったトリック

Posted at

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を作成する際などに便利かと思います。

0
0
0

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
0
0