2017-06-13 5 views
4

同僚は、純粋なES6 JavaScriptクラスをAngularに注入する方法が間違っていると主張しています。より良い方法があれば好奇心旺盛です(より正確です)?純粋なクラスをES6の角度1.xアプリケーションに注入する正しい方法

これに加えて、注入された依存関係(この例では$timeout)をインスタンスに添付する方が良い(それがなぜ良いか)。例えば、this._$timeout = $timeoutをコンストラクタ内に挿入する。私は個人的にこの場合、それをすることに利点がないと思っています。

class.factory.js

import ClassFactory from './factories/class.factory'; 
import AppService from './services/app.service'; 


export default angular.module('myApp', []) 
    .factory('ClassFactory', ClassFactory) 
    .service('AppService', AppService); 

その後

let ClassFactory = function($timeout) { 
    // Factory function that simply returns class constructor. 

    class MyClass { 
     constructor(a, b) { 
      // contrived class 
      this.a = a; 
      this.b = b; 
      this.c = null; 
     } 

     applyChange() { 
      // contrived class method 
      const SELF = this; 

      $timeout(() => { 
       SELF.c = SELF.a + SELF.b; 
      }); 
     } 
    } 

    return MyClass ; 
}; 

ClassFactory.$inject = ['$timeout']; 

export default ClassFactory; 

app.module.js、他の場所で、私たちは新しいMyClassのを構築するために、いくつかのサービスまたはコントローラでクラスを使用することができますインスタンス。

app.service.jsこの時点で

class AppService { 
    // contrived usage of our dependency injected pure class. 

    constructor(ClassFactory) { 
     this.array = []; 
     this._ClassFactory = ClassFactory; 
    } 

    initialize(a, b) { 
     // We can instantiate as many "MyClass" objects as we need. 
     let myClass = new this._ClassFactory(a, b); 

     this.array.push(myClass); 
    } 

    static serviceFactory(...injected) { 
     AppService.instance = new AppService(...injected); 
     return AppService.instance; 
    } 
} 

AppService.serviceFactory.$inject = ['ClassFactory']; 

export default AppService.serviceFactory; 
+1

AppService.instance =新しいAppServiceのような処理もお勧めできません。アプリケーションインスタンスが1つしかなく、サービスがシングルトンであるため、通常は正常に動作します。しかし、テスト中にメモリリークが発生します。 – estus

答えて

3

$timeoutはクラスプロパティまたは単にローカル変数であれば、それは問題ではありません。

ファクトリ関数を使用したクラスのラッピングは、ES6開発ではうまく動作しません。エクスポートして拡張することはできません。工場が必要であるという事実はおそらく設計上の問題を示している。

そのようなクラスは、依存性注入(common sense)によって依存関係を取得できます。このクラスのコンストラクタは、あまりにも非依存の引数で呼び出されることになっているとき、通常のものである:

export class MyClass { 
    constructor($timeout, a, b) { 
    this._$timeout = $timeout; 
    ... 
    } 
} 
... 
obj = new MyClass($timeout, a, b); 

つ以上の依存関係があれば、$injector依存関係ではなく、すべての依存関係を提供することができます。

export class MyClass { 
    constructor($injector, a, b) { 
    this._$timeout = $injector.get('$timeout'); 
    ... 
    } 
} 
... 
obj = new MyClass($injector, a, b); 

$timeoutへの依存を引き起こす設計上の問題があり、それを解決することによって依存関係を回避することができます。上記のコードからMyClassがダイジェストを$timeoutでトリガーする必要があることは明らかではありませんが、そのロジックには必要なものは含まれていません。これは、MyClassインスタンスを使用するコードの責任であり、ダイジェストを表示するためにそれをバインドします。

+0

これは人為的な例です。しかし実際のクラスでは、いくつかのAngularフィーチャにアクセスする必要があります。 '$ timeout'の本当の使い方は、(狭い条件のもとで)Angularダイジェストサイクルをトリガして、クラスインスタンスの変更が伝播するようにすることです。 – James

+0

この例で '$ injector'を使用した例はありますか?そしてあなたの他のコメントには、純粋なES6クラスをAngularで使用する方法を説明する良いリソースは見つかりませんでした。クラスを返すためにファクトリを使うことは、私が見つけることができる最も近いものでした。 – James

+1

@TechMedicNYCが追加されました。はい、それはかなりプロフィールではなく、ガイドで通常議論されるものではありません。ファクトリ関数は非モジュール式ES5で実行される方法ですが、ES6では十分ではありません。 – estus

関連する問題