2012-11-28 80 views
20

用例很簡單:我有兩個控制器共享相同的依賴關係MyService。這項服務正在舉辦一些狀態,讓坐在myVariable。如果我從ControllerOne設置它,那麼它也會被ControllerTwo發現。告訴AngularJs通過依賴注入返回一個新實例

我想要的是每個控制器都有自己的實例MyService,這樣myVariable可以由每個控制器更改而不會影響其他控制器。

爲了把它放在另一個詞 - 我想新實例由依賴注入返回,而不是單

+0

另請參閱http://stackoverflow.com/a/13620494/215945 –

回答

20

不是你可能希望的那樣直接。服務實例首次被注入器檢索並由注入器維護時創建......換句話說,它們始終是單例。 The magic happens in here,特別是看看provider函數,該函數將provider實例放入providerCache對象中。

但不要失去希望,你可以很容易地添加構造函數無論是你想在一個服務共享,如果你願意的選擇:

app.factory('myService', [function() { 
    var i = 1; 

    function Foo() { 
     this.bar = "I'm Foo " + i++; 
    }; 

    return { 
      Foo: Foo 
    }; 
}]); 

app.controller('Ctrl1', function($scope, myService) { 
    $scope.foo = new myService.Foo(); 
    console.log($scope.foo.bar) //I'm Foo 1 
}); 

app.controller('Ctrl2', function($scope, myService) { 
    $scope.foo = new myService.Foo(); 
    console.log($scope.foo.bar) //I'm Foo 2 
}); 

編輯:作爲OP指出,還有$injector.instantiate,您可以使用它來調用控制器外部的JavaScript構造函數。我不確定這裏對可測試性有什麼影響,但它確實爲您提供了另一種注入代碼的方法,可以爲您構建一個新的對象。

+4

還有另一種方法。您可以簡單地創建一個具有所需依賴關係的對象(Component X),然後直接用'$ injector.instantiate(ComponentX,{})'注入它。第二個參數可能包含所有'statefull'變量。簡單而優雅,謝謝Angular Js! 也許您可以將其添加到您的回覆中作爲替代解決方案嗎? –

+1

似乎很難測試。 –

+0

似乎是解決方案,但您只需要返回構造函數。除非將它們添加到構造函數的原型中,否則所有其他方法都不會影響您稍後創建的任何實例...請參閱karlgold答案,這幾乎是完美的。 –

3

有大量的用於模塊化JavaScript代碼常規選項,但是如果你想要做的東西,完全依賴於AngularJS,這種模式的工作原理:

1)首先確定要注射多次類:

function MyClass() { 
    // ... 
} 

MyClass.prototype.memberMethod = function() { 
    // ... 
} 

2)接着,使可作爲一個恆定的構造:

angular.module('myModule').constant('MyClass', MyClass); 

3)最後,使用工廠模式來創建命名,注射類實例:

angular.module('myOtherModule', ['myModule']).factory('instanceOfMyClass', [ 
    'MyClass', 
    function(MyClass) { return new MyClass(); } 
]); 
+0

好主意。但是,如果你的原型需要使用常量不能完成的注入,這兩個值都不起作用。在這種情況下,我想創建一個服務是一個更好的選擇。 –