Jak mogę przetestować usługę AngularJS z konsoli?

395

Mam taką usługę jak:

angular.module('app').factory('ExampleService', function(){
  this.f1 = function(world){
    return 'Hello '+world;
  }
  return this;
})

Chciałbym przetestować go z konsoli JavaScript i wywołać funkcję f1()usługi.

Jak mogę to zrobić?

JustGoscha
źródło

Odpowiedzi:

713

TLDR: W jednej linii szukasz polecenia:

angular.element(document.body).injector().get('serviceName')

Głębokie nurkowanie

AngularJS używa Dependency Injection (DI) do wstrzykiwania usług / fabryk do komponentów, dyrektyw i innych usług. Aby więc uzyskać usługę, musisz najpierw pobrać wtryskiwacz AngularJS (wtryskiwacz jest odpowiedzialny za połączenie wszystkich zależności i dostarczenie ich do komponentów).

Aby uzyskać wtryskiwacz aplikacji, musisz pobrać go z elementu, który obsługuje kąt. Na przykład, jeśli Twoja aplikacja jest zarejestrowana w elemencie ciała, do którego dzwoniszinjector = angular.element(document.body).injector()

Po odzyskaniu injectormożesz uzyskać dowolną usługęinjector.get('ServiceName')

Więcej informacji na ten temat w tej odpowiedzi: Nie można pobrać wtryskiwacza z kątownika
I jeszcze więcej tutaj: Zadzwoń do AngularJS ze starszego kodu


Kolejna przydatna sztuczka pozwalająca uzyskać $scopeokreślony element. Wybierz element za pomocą narzędzia inspekcji DOM narzędzi programistycznych, a następnie uruchom następującą linię ( $0zawsze jest wybranym elementem):
angular.element($0).scope()

JustGoscha
źródło
70
Musiałem też to zrobić, aby działało. BTW, angular.element('*[ng-app]').injector()powinien działać we wszystkich przypadkach.
Francesc Rosas,
4
Jeśli wystąpi błąd „selektory nie zostały zaimplementowane” podczas wykonywania angular.element („html”), możesz użyć funkcji Chrome 0 USD. Wybierz element HTML, przejdź do konsoli i uruchom angular.element (0 $) .injector ()
Marek
9
documentdziała również:angular.element(document).injector().get('serviceName')
Tamlyn
1
Do twojej wiadomości musiałem użyć document.body na chrome
Kevin
5
Do Twojej wiadomości chciałem skorzystać z usługi lokalizacji $, ale ostatecznie musiałem ją zawinąć w scope.apply. Wiem, że jest to dobrze udokumentowane, ale wymknęło mi się z głowy. W jednej linii angular.element (document) .scope (). $ Apply (angular.element (document) .injector (). Get ('$ location'). Path ('/ my /
angular
25

Przede wszystkim zmodyfikowana wersja twojej usługi.

a)

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

app.factory('ExampleService',function(){
    return {
        f1 : function(world){
            return 'Hello' + world;
        }
    };
});

Zwraca obiekt, nic nowego.

Teraz sposobem na uzyskanie tego z konsoli jest

b )

var $inj = angular.injector(['app']);
var serv = $inj.get('ExampleService');
serv.f1("World");

c)

Jedną z rzeczy, które robiłeś tam wcześniej, było założenie, że fabryka aplikacji zwraca ci samą funkcję lub jej nową wersję. Co nie jest prawdą. Aby uzyskać konstruktora, musiałbyś to zrobić

app.factory('ExampleService',function(){
        return function(){
            this.f1 = function(world){
                return 'Hello' + world;
            }
        };
    });

Zwraca to konstruktor ExampleService, na którym będziesz musiał zrobić „nowy”.

Lub alternatywnie

app.service('ExampleService',function(){
            this.f1 = function(world){
                return 'Hello' + world;
            };
    });

Zwraca to nową ExampleService () po wstrzyknięciu.

ganaraj
źródło
3
kiedy to robię, var $inj = angular.injector(['app']);konsola rzuca Error: Unknown provider: $filterProvider from appw jednej aplikacji i Error: Unknown provider: $controllerProvider from appw innej aplikacji ...
JustGoscha
@JustGoscha Jak skonfigurowana jest Twoja aplikacja? tj. W jaki sposób linia (która wygląda) var app = angular.module ('app', []); wygląda jak w twojej aplikacji.
ganaraj
Nie do końca rozumiem pytanie ... wygląda tak, jak mówisz, angular.module('app',[]);a potem są różne usługi, kontrolery itp. W różnych plikach i wszystkie są zdefiniowane jak angular.module('app').factory('FeatureRegistry',function(){//code here});na przykład
JustGoscha
@JustGoscha Oto, co zrobiłem, aby przetestować. Poszedłem do docs.quarejs.org/api w chrome. Otworzyłem konsolę. Wpisz kod w sekcji a mojej odpowiedzi, a następnie wpisz kod w sekcji b. Powinieneś zobaczyć Hello World. Możesz spróbować?
ganaraj
14

@ Odpowiedź JustGoscha jest natychmiastowa, ale to dużo do wpisania, gdy chcę uzyskać dostęp, więc dodałem to na dole mojej aplikacji.js. Następnie wszystko, co muszę wpisać, to x = getSrv('$http')uzyskać usługę http.

// @if DEBUG
function getSrv(name, element) {
    element = element || '*[ng-app]';
    return angular.element(element).injector().get(name);
}
// @endif

Dodaje to do zasięgu globalnego, ale tylko w trybie debugowania. Umieszczam go wewnątrz @if DEBUG, aby nie skończyć z kodem produkcyjnym. Używam tej metody do usuwania kodu debugowania z kompilacji dumy.

Boatcoder
źródło
4

Struktura Angularjs Dependency Injection jest odpowiedzialna za wstrzyknięcie kontrolerom zależności twojego modułu aplikacji. Jest to możliwe dzięki wtryskiwaczowi.

Musisz najpierw zidentyfikować aplikację ng i uzyskać powiązany wtryskiwacz. Poniższe zapytanie działa, aby znaleźć twoją aplikację ng w DOM i pobrać wtryskiwacz.

angular.element('*[ng-app]').injector()

W wersji chromowanej możesz jednak wskazać docelową aplikację ng, jak pokazano poniżej. i użyj $0hacka i problemuangular.element($0).injector()

Gdy masz już wtryskiwacz, skorzystaj z usługi wstrzykiwania zależności, jak poniżej

injector = angular.element($0).injector();
injector.get('$mdToast');

wprowadź opis zdjęcia tutaj

Faiz Mohamed Haneef
źródło