ngOnInit nie jest wywoływany podczas tworzenia instancji klasy Injectable

197

Dlaczego nie jest ngOnInit()wywoływany, gdy Injectableklasa jest rozstrzygana?

Kod

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

}

Wyjście konsoli

FROM constructor()
Levi Fuller
źródło

Odpowiedzi:

313

Haki cyklu życia , takie jak OnInit()praca z dyrektywami i komponentami. Nie działają z innymi typami, takimi jak usługa w twoim przypadku. Z dokumentów:

Cykl życia komponentu zarządzany jest przez sam Angular. Angular go tworzy, renderuje, tworzy i renderuje swoje dzieci, sprawdza, kiedy właściwości powiązane z danymi zmieniają się i niszczą przed usunięciem go z DOM.

Instancje dyrektyw i komponentów mają cykl życia, gdy Angular je tworzy, aktualizuje i niszczy.

Sasxa
źródło
38
Więc po prostu przenieś moją ngOnInitlogikę do konstruktora dla Injectableklas? Właśnie przypomniałem sobie, że z jakiejkolwiek przyczyny powinieneś trzymać konstruktor w logice.
Levi Fuller
48
@LeviFuller Tak, w przypadku usług można wykonać inicjalizację w konstruktorze lub lepiej wykonać metodę init i wywołać ją z konstruktora (na wypadek, gdyby trzeba było później zresetować usługę).
Sasxa
9
Nie do końca OnInit ma związek z wiązaniem. Używasz go, gdy chcesz poczekać na rozwiązanie wartości wejściowych, ponieważ nie są one dostępne w konstruktorze. Konstruktor można wywoływać wiele razy. Na przykład, kiedy zmieniasz trasę i
ładujesz
5
Warto również zauważyć, że usługi Sevice mogą być tworzone wielokrotnie, w zależności od tego, gdzie umieścisz je w providerstablicach. Jeśli chcesz skorzystać z usługi singleton, umieść ją w module głównym providers, a jeśli chcesz, aby usługi dla poszczególnych komponentów dodawały je bezpośrednio do komponentu.
Askdesigners,
4
Nie jest to całkowicie niepoprawne, ponieważ @ SBD580 wskazuje w odpowiedzi na ngOnDestroywezwanie do wstrzykniętych usług
shusson
48

Nie wiem o wszystkich hakach cyklu życia, ale jeśli chodzi o zniszczenie, ngOnDestroy faktycznie wywoływany jest na Injectable, gdy jego dostawca jest zniszczony (na przykład Injectable dostarczany przez komponent).

Od docs :

Hak cyklu życia, który jest wywoływany w przypadku zniszczenia dyrektywy, rury lub usługi .

Jeśli ktoś jest zainteresowany zniszczeniem, sprawdź to pytanie:

SBD580
źródło
2
taki wstyd ngOnInitnie jest nazywany :-( Naprawdę chciałem wykonać przezroczystą magię opóźnionej inicjalizacji. Jeśli ngOnDestroymożna to nazwać, nie rozumiem, dlaczego init nie może
Simon_Weaver
2

Uwaga: ta odpowiedź dotyczy tylko komponentów i dyrektyw Angular, NIE usług.

Miałem ten sam problem, gdy ngOnInit(i inne haki cyklu życia) nie strzelały do ​​moich komponentów, a większość wyszukiwań doprowadziła mnie tutaj.

Problem polega na tym, że używałem składni funkcji strzałki ( =>) w następujący sposób:

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

Najwyraźniej to nie działa w Angular 6. Użycie składni funkcji innej niż strzałka rozwiązuje problem:

class MyComponent implements OnInit {
    public ngOnInit() {
        console.log("ngOnInit");
    }
}
AJ Richardson
źródło
Klasy do wstrzykiwania to Usługi, a nie Komponenty. OP pyta o usługę. Chociaż twoja odpowiedź może być poprawna z POV języka, nie odpowiada na to pytanie. Powinieneś go usunąć.
Andrew Philips
@AndrewPhilips, podczas gdy mój przypadek użycia różni się nieco od PO, wyszukiwanie w Google „ngOnInit not wezwał” prowadzi ludzi tutaj. Moim celem z tą odpowiedzią nie jest pomoc OP, ale pomoc każdemu z ponad 70 000 widzów, którzy mogą mieć podobne problemy ngOnInit.
AJ Richardson
Słusznie. Wydaje mi się, że widziałem SO pytania i odpowiedzi, w których autor pyta, a następnie odpowiada na własne pytanie. Jako nowy programista Angular Twoja odpowiedź pomyliłaby mnie dwa tygodnie temu. Zarówno z perspektywy SO, jak i NG uważam, że twoja odpowiedź jest warta własnego pytania, więc nie została usunięta, ale „przeklasyfikowana”. Kto wie? Być może może dotrzeć do jeszcze szerszego grona odbiorców. Twoje zdrowie.
Andrew Philips
1
Ma sens - zredagowałem swoją odpowiedź, aby wyjaśnić, że nie dotyczy to usług.
AJ Richardson
0

Musiałem wywołać funkcję po zainicjowaniu mojej usługi danych, zamiast tego nazwałem ją w konstruktorze, który działał dla mnie.

Eduardo A EDUARDO Fernandez Di
źródło
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
źródło