Wie kann ich einen AngularJS-Dienst von der Konsole aus testen?


395

Ich habe einen Service wie:

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

Ich möchte es von der JavaScript-Konsole aus testen und die Funktion f1()des Dienstes aufrufen .

Wie kann ich das machen?

Antworten:


713

TLDR: In einer Zeile der gesuchte Befehl:

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

Tieftauchgang

AngularJS verwendet Dependency Injection (DI) , um Services / Fabriken in Ihre Komponenten, Direktiven und andere Services einzufügen. Um einen Service zu erhalten, müssen Sie zuerst den Injektor von AngularJS erhalten (der Injektor ist dafür verantwortlich, alle Abhängigkeiten zu verdrahten und für Komponenten bereitzustellen).

Um den Injektor Ihrer App zu erhalten, müssen Sie ihn von einem Element abrufen, das eckig ist. Zum Beispiel, wenn Ihre App auf dem von Ihnen aufgerufenen Body-Element registriert istinjector = angular.element(document.body).injector()

Aus dem abgerufenen können injectorSie dann jeden gewünschten Service erhalteninjector.get('ServiceName')

Weitere Informationen dazu in dieser Antwort: Der Injektor kann nicht aus dem Winkel abgerufen werden.
Und noch mehr hier: Rufen Sie AngularJS aus dem Legacy-Code auf


Ein weiterer nützlicher Trick, um das $scopeeines bestimmten Elements zu erhalten. Wählen Sie das Element mit dem DOM-Inspektionstool Ihrer Entwicklertools aus und führen Sie dann die folgende Zeile aus ( $0ist immer das ausgewählte Element):
angular.element($0).scope()


70
Ich musste das auch tun, damit es funktionierte. Übrigens angular.element('*[ng-app]').injector()sollte in allen Fällen funktionieren.
Francesc Rosas

4
Wenn beim Ausführen von angle.element ('html') die Fehlermeldung 'Selektoren nicht implementiert' angezeigt wird, können Sie die Chrome $ 0-Funktion verwenden. Wählen Sie HTML-Element, gehen Sie zur Konsole und führen Sie angle.element ($ 0) .injector ()
Marek

9
documentfunktioniert auch:angular.element(document).injector().get('serviceName')
Tamlyn

1
Zu Ihrer Information, ich musste document.body auf Chrom verwenden
Kevin

5
Zu Ihrer Information Ich wollte $ location service verwenden, musste es aber schließlich in scope.apply einbinden. Ich weiß, dass dies gut dokumentiert ist, aber es war mir durch den Kopf gegangen. In einer Zeile angle.element (document) .scope (). $ Apply (angle.element (document) .injector (). Get ('$ location'). Path ('/ my /
angle

25

Zunächst eine modifizierte Version Ihres Dienstes.

ein )

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

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

Dies gibt ein Objekt zurück, hier nichts Neues.

Nun ist der Weg, dies von der Konsole zu bekommen, ist

b)

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

c)

Eines der Dinge, die Sie dort zuvor getan haben, war anzunehmen, dass die app.factory Ihnen die Funktion selbst oder eine neue Version davon zurückgibt. Welches ist nicht der Fall. Um einen Konstruktor zu erhalten, müssten Sie entweder tun

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

Dies gibt einen ExampleService-Konstruktor zurück, für den Sie als Nächstes ein 'neues' ausführen müssen.

Oder alternativ,

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

Dies gibt beim Injection neuen ExampleService () zurück.


3
Wenn ich das tue, var $inj = angular.injector(['app']);wirft die Konsole eine Error: Unknown provider: $filterProvider from appin einer App und Error: Unknown provider: $controllerProvider from appin einer anderen App ...
JustGoscha

@JustGoscha Wie ist deine App konfiguriert? dh wie funktioniert eine Linie (die aussieht) var app = angle.module ('app', []); siehst aus wie in deiner App.
Ganaraj

Ich verstehe die Frage nicht ganz. Es sieht so aus, wie Sie es sagen, angular.module('app',[]);und dann gibt es Dienste, Controller usw. in verschiedenen Dateien und sie sind alle wie angular.module('app').factory('FeatureRegistry',function(){//code here});zum Beispiel definiert
JustGoscha

@ JustGoscha Hier ist, was ich getan habe, um zu testen. Ich ging zu docs.angularjs.org/api in Chrom. Öffnete die Konsole. Geben Sie den Code in Abschnitt a meiner Antwort ein und geben Sie dann den Code in Abschnitt b ein. Sie sollten Hello World sehen. Können Sie das versuchen?
Ganaraj

14

Die Antwort von @ JustGoscha ist genau richtig, aber das ist eine Menge zu tippen, wenn ich Zugriff haben möchte, also habe ich dies am Ende meiner app.js hinzugefügt. Dann muss ich nur x = getSrv('$http')noch den http-Dienst abrufen.

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

Es fügt es dem globalen Bereich hinzu, jedoch nur im Debug-Modus. Ich habe es in das @if DEBUGeingefügt, damit es nicht im Produktionscode landet. Ich benutze diese Methode, um Debug-Code aus Prideuction-Builds zu entfernen.


4

Das Angularjs Dependency Injection Framework ist dafür verantwortlich, die Abhängigkeiten Ihres App-Moduls in Ihre Controller zu injizieren. Dies ist durch seinen Injektor möglich.

Sie müssen zuerst die ng-App identifizieren und den zugehörigen Injektor erhalten. Die folgende Abfrage dient dazu, Ihre ng-App im DOM zu finden und den Injektor abzurufen.

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

In Chrome können Sie jedoch wie unten gezeigt auf die Ziel-ng-App zeigen. und benutze den $0Hack und das Problemangular.element($0).injector()

Sobald Sie den Injektor haben, erhalten Sie einen Abhängigkeitsinjektionsdienst wie unten

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

Geben Sie hier die Bildbeschreibung ein

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.