ngOnInit wird nicht aufgerufen, wenn die Klasse Injectable instanziiert ist

196

Warum wird nicht ngOnInit()aufgerufen, wenn eine InjectableKlasse aufgelöst wird?

Code

import {Injectable, OnInit} from 'angular2/core';
import { RestApiService, RestRequest } from './rest-api.service';

@Injectable()
export class MovieDbService implements OnInit {

    constructor(private _movieDbRest: RestApiService){
        window.console.log('FROM constructor()');
    }

    ngOnInit() {
         window.console.log('FROM ngOnInit()');
    }

}

Konsolenausgabe

FROM constructor()
Levi Fuller
quelle

Antworten:

312

Lifecycle-Hooks , wie die OnInit()Arbeit mit Direktiven und Komponenten. Sie funktionieren nicht mit anderen Typen, wie z. B. einem Dienst in Ihrem Fall. Aus Dokumenten:

Eine Komponente hat einen Lebenszyklus, der von Angular selbst verwaltet wird. Angular erstellt es, rendert es, erstellt und rendert seine untergeordneten Elemente, überprüft es, wenn sich seine datengebundenen Eigenschaften ändern, und zerstört es, bevor es aus dem DOM entfernt wird.

Direktiven- und Komponenteninstanzen haben einen Lebenszyklus, da Angular sie erstellt, aktualisiert und zerstört.

Sasxa
quelle
38
Verschieben Sie meine ngOnInitLogik einfach in den Konstruktor für InjectableKlassen? Ich habe mich gerade daran erinnert zu lesen, dass Sie aus irgendeinem Grund jede Logik aus dem Konstruktor heraushalten sollten.
Levi Fuller
48
@LeviFuller Ja, für Dienste können Sie die Initialisierung im Konstruktor durchführen oder besser die init-Methode erstellen und vom Konstruktor aus aufrufen (falls Sie einen Dienst später zurücksetzen müssen).
Sasxa
9
Nicht genau, OnInit hat mit Bindung zu tun. Sie verwenden es, wenn Sie auf die Auflösung von Eingabewerten warten möchten, da diese im Konstruktor nicht verfügbar sind. Der Konstruktor kann mehrfach aufgerufen werden. Wenn Sie beispielsweise die Route ändern und verschiedene Komponenten laden, werden diese jedes Mal "konstruiert" und zerstört ...
Sasxa,
5
Es ist auch hier erwähnenswert, dass Sevices können mehrfach instanziert werden, je nachdem , wo man sie in sind providersArrays. Wenn Sie einen Singleton-Dienst providerswünschen, fügen Sie ihn in das Hauptmodul ein , und wenn Sie Dienste pro Komponente wünschen, fügen Sie diese direkt zur Komponente hinzu.
Askdesigners
4
Dies ist nicht ganz falsch, da @ SBD580 Punkte in seiner Antwort ngOnDestroyfür injizierte Dienste aufgerufen wird
Shusson
48

Ich kenne nicht alle Lifecycle-Hooks, aber was die Zerstörung ngOnDestroybetrifft , werde ich tatsächlich auf Injectable aufgerufen, wenn der Provider zerstört wird (zum Beispiel ein Injectable, das von einer Komponente bereitgestellt wird).

Von dem docs :

Lifecycle-Hook, der aufgerufen wird, wenn eine Direktive, eine Pipe oder ein Dienst zerstört wird.

Nur für den Fall, dass jemand an Zerstörung interessiert ist, überprüfen Sie diese Frage:

SBD580
quelle
2
Eine solche Schande ngOnInitheißt nicht :-( Ich wollte wirklich eine transparente Magie der verzögerten Initialisierung machen. Wenn ngOnDestroysie aufgerufen werden kann, verstehe ich nicht, warum init nicht kann
Simon_Weaver
3

Hinweis: Diese Antwort gilt nur für Angular-Komponenten und -Anweisungen, NICHT für Dienste.

Ich hatte das gleiche Problem, als ngOnInit(und andere Lifecycle-Hooks) nicht für meine Komponenten ausgelöst wurden, und die meisten Suchanfragen führten mich hierher.

Das Problem ist, dass ich die Pfeilfunktionssyntax ( =>) wie folgt verwendet habe :

class MyComponent implements OnInit {
    // Bad: do not use arrow function
    public ngOnInit = () => {
        console.log("ngOnInit");
    }
}

Anscheinend funktioniert das in Angular 6 nicht. Die Verwendung der Nicht-Pfeil-Funktionssyntax behebt das Problem:

class MyComponent implements OnInit {
    public ngOnInit() {
        console.log("ngOnInit");
    }
}
AJ Richardson
quelle
Injizierbare Klassen sind Services, keine Komponenten. OP fragt nach einem Service. Obwohl Ihre Antwort aus einem Sprach-POV korrekt ist, beantwortet sie diese Frage nicht. Sie sollten es löschen.
Andrew Philips
@AndrewPhilips Während sich mein Anwendungsfall geringfügig von den OPs unterscheidet, führt eine Google-Suche nach "ngOnInit nicht aufgerufen" die Leute hierher. Mein Ziel mit dieser Antwort ist es nicht, dem OP zu helfen, sondern einem der anderen über 70.000 Zuschauer zu helfen, die möglicherweise ähnliche Probleme haben ngOnInit.
AJ Richardson
Meinetwegen. Ich glaube, ich habe SO Q & A gesehen, in denen ein Autor seine eigene Frage stellt und dann beantwortet. Als neuer Angular-Programmierer hätte mich Ihre Antwort vor zwei Wochen verwirrt. Sowohl aus SO- als auch aus NG-Sicht denke ich, dass Ihre Antwort eine eigene Frage verdient, also nicht gelöscht, sondern „neu kategorisiert“. Wer weiß? Vielleicht könnte es ein noch breiteres Publikum erreichen. Prost.
Andrew Philips
1
Sinnvoll - Ich habe meine Antwort bearbeitet, um deutlich zu machen, dass dies nicht für Dienste gilt.
AJ Richardson
0

Ich musste eine Funktion aufrufen, nachdem mein dataService initialisiert wurde. Stattdessen habe ich sie im Konstruktor aufgerufen, der für mich funktioniert hat.

Eduardo A EDUARDO Fernandez Di.
quelle
0
import {Injectable, OnInit} from 'angular2/core';
import { RestApiService, RestRequest } from './rest-api.service';
import {Service} from "path/to/service/";

@Injectable()
export class MovieDbService implements OnInit {

userId:number=null;

constructor(private _movieDbRest: RestApiService,
            private instanceMyService : Service ){

   // do evreything like OnInit just on services

   this._movieDbRest.callAnyMethod();

   this.userId = this.instanceMyService.getUserId()


}
HSN KH
quelle