2012-11-28 17 views
20

Przypadek użycia jest prosty: Mam dwa kontrolery współużytkujące tę samą zależność MyService. Ta usługa trzyma pewien stan, pozwala usiąść myVariable. Jeśli ustawię go z ControllerOne, zostanie on również zauważony przez ControllerTwo.Poinformuj AngularJs, aby zwrócił nową instancję za pomocą Dependency Injection

Potrzebuję, aby każdy kontroler posiadał własną instancję MyService, dzięki czemu myVariable może być zmieniany przez każdy kontroler bez wpływu na drugi.

Mówiąc innymi słowami - Chcę zostać zwrócone przez Dependency Injection, zamiast singletonnową instancję.

+0

Zobacz także http://stackoverflow.com/a/13620494/215945 –

Odpowiedz

20

Nie tak bezpośrednio, jak możesz mieć nadzieję. Instancje serwisowe są tworzone przy pierwszym pobieraniu przez wtryskiwacz i utrzymywane przez wtryskiwacz ... Innymi słowy, są to pojedyncze egzemplarze. The magic happens in here, szczególnie spójrz na funkcję provider, która umieszcza instancję dostawcy w obiekcie providerCache.

Ale nie tracić nadziei, można równie łatwo dodać konstruktorów na cokolwiek to jest chcesz udostępniać w Serwisie, jeśli tak wybrał:

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 
}); 

EDIT: jak PO zwrócił uwagę, istnieje również $injector.instantiate, którego można użyć do wywołania konstruktorów JavaScript poza kontrolerem. Nie jestem pewien, jakie są implikacje tutaj testowalności, ale daje to inny sposób na wstrzyknięcie kodu, który skonstruuje dla ciebie nowy obiekt.

+4

Istnieje również inny sposób. Możesz po prostu utworzyć obiekt z wymaganymi zależnościami (Komponent X), a następnie wstrzyknąć go bezpośrednio za pomocą '$ injector.instantiate (ComponentX, {})'. Drugi argument może zawierać wszystkie zmienne "statefull". Łatwo i elegancko, dziękuję Angular Js! Może powinieneś dodać to do swojej odpowiedzi jako alternatywne rozwiązanie? –

+1

Wydaje się trudniejsze do przetestowania. –

+0

Wydaje się być rozwiązaniem, ale musisz zwrócić tylko konstruktora. Wszystkie inne metody, które można odłożyć na bok, nigdy nie wpłyną na żadne instancje, które utworzysz później, chyba że dodasz je do prototypu swojego konstruktora ... Zobacz odpowiedź karlgold, która jest prawie idealna. –

3

Istnieje wiele opcji ogólnych dla modularyzacji kodu JavaScript, ale jeśli chcesz zrobić coś, co opiera się wyłącznie na angularjs, ten wzór działa:

1) najpierw zdefiniować klasę, którą chcesz wprowadzić wiele razy:

function MyClass() { 
    // ... 
} 

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

2) Następnie należy dokonać konstruktora dostępne jako Constant:

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

3) Wreszcie, należy użyć wzoru fabrycznego stworzyć nazwane, wstrzykiwania instancjami klasy:

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

Dobry pomysł. Ale to nie działa, jeśli twój prototyp potrzebuje zastrzyków, których nie da się zrobić za pomocą stałych, ani wartości ... W tym przypadku, myślę, że stworzenie usługi jest lepszą opcją. –

Powiązane problemy