LoginSignup
16
19

More than 5 years have passed since last update.

AngularJSでよく見るDependency Injectionについて

Posted at

AngularJSでよく見かける書き方

var myModule = angular.module('myModule', []);

とか、

myModule.factory('greeter', function($window) {
return {
  greet: function(text) {
    $window.alert(text);
  }
};
});

というようにAngularJSでは独特の書き方をします。
このような書き方はDependency Injection(DI)という書き方だそうです。

AngularJSでのDIに関するドキュメント
https://docs.angularjs.org/guide/di

AngularJSでのDI部分のコード
https://github.com/angular/angular.js/blob/master/src/auto/injector.js

DIについて

img01.jpg

AngularJSリファレンスという本でもDIについて解説がされています(DIとは、P.129)。

DI(Dependency Injection)とは、あるコンポーネントから別のコンポーネントを利用する際に直接コンポーネントを呼び出すコードを記述するのではなく、設定ファイルやアノテーション機能を使ってコンポーネント間の依存関係を記述し、実行時に依存関係を解決するというデザインパターンです。

DIについて色々と詳しく書かれているので、興味がある人は是非読むのをオススメします。

普通書くときにコンポーネントを直接呼び出すのに慣れています。
1 - 依存関係を記述し、 2 - 実行時に依存関係を記述するという2段感あると一気に複雑に思えます。

簡易版AngularJSでDenpendency Injectionを体験する

AngularJS式Injectionを解説しているブログがありましたので、実際試し、メモしました。

var WelcomeController = function (Greeter) {
  /** I want a different Greeter injected dynamically. **/
    Greeter.greet();
};

AngularJSでは引数の名前がdependencyの名前であります。
引数の名前は重要で、実際のdependencyとdepencyの名前が関連付けられます。

WelocomControlleが動くようにDIを作ってみます。

DIの機能として、1 - 依存関係を記述するメソッドと 2 - 依存関係を実行するメソッドが必要となります。

1 - 依存関係を記述するメソッド

var Injector = {
    depnedencies : {},
    register     : function(name, dependency){
        this.depnedencies[name] = dependency;
    }
}

var RobotGreeter = {
  greet: function() {
    return 'Domo Arigato';
  }
};

Injector.register('Greeter', RobotGreeter);

RobertGreeterというオブジェクトを'greeter'として依存関係を登録する。

2 - 依存関係を実行するメソッド

var Injector = {
    depnedencies : {},
    register     : function(name, dependency){
        this.depnedencies[name] = dependency;
    },
    process : function(target){

    }
}

Injector.register('Greeter', RobotGreeter);
Injector.process(WelcomeController);

WelcomeControllerを実行します。

どのように実行するか、、、という問題が出てきます。

var Injector = {

    dependencies: {},

    process: function(target) {
        var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
        var text = target.toString();
        var args = text.match(FN_ARGS)[1].split(',');

        target.apply(target, this.getDependencies(args));
    },

    getDependencies: function(arr) {
        var self = this;
        return arr.map(function(value) {
            return self.dependencies[value];
        });            
    },

    register: function(name, dependency) {
        this.dependencies[name] = dependency;
    }

};

processでは、正規表現をつかって関数の引数を取ります。
applyで関数に引数を代入します。

サンプルはこんな感じでした。

DIを利用してCanvasを描画する。

// DI

var Injector = {

    dependencies: {},

    process: function(target) {
        var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
        var FN_ARG_SPLIT = /,/;
        var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
        var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
        var text = target.toString();
        var args = text.match(FN_ARGS)[1].split(',');

        var a = this.getDependencies(args);
        console.log(target);
        console.log("-----\n");
        console.log(a);

        target.apply(this, a);
    },

    getDependencies: function(arr) {
        var self = this;
        return arr.map(function(value) {

            return self.dependencies[value];
        });            
    },

    register: function(name, dependency) {
        this.dependencies[name] = dependency;
    }

};

// ============================
//         Canvasアプリ
// ============================

var CanvasApp = {
  width  : null,
  height : null,
  canvas : null,
  ctx    : null,

  setup  : function(){
    this.width  = window.innerWidth;
    this.height = window.innerHeight;
    this.canvas = document.getElementById('c');
    this.canvas.width = this.width;
    this.canvas.height = this.height;

    this.ctx = this.canvas.getContext('2d');
  },
  draw   : function(){
    this.ctx.fillStyle = '#ff0000';
    this.ctx.fillRect(100, 100, 100, 100);
  }
};

// ============================
//        コントローラ
// ============================

var CanvasAppController = function (paintApp) {
    paintApp.setup();
    paintApp.draw();
};

// 1.dependencyをに'paintApp'としてCanvasAppを登録
Injector.register('paintApp', CanvasApp);

// 2.実行する
Injector.process(CanvasAppController);

結果は下のリンクから見ることができます。
http://codepen.io/kenjiSpecial/pen/GBpnE

DIを知ったつもりになりましたー
AngularJS色々と学ぶことが多いです。。

16
19
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
16
19