ngOnInit não está sendo chamado quando a classe injetável é instanciada

197

Por que não é ngOnInit()chamado quando uma Injectableclasse é resolvida?

Código

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

}

Saída do console

FROM constructor()
Levi Fuller
fonte

Respostas:

312

Ganchos de ciclo de vida , como o OnInit()trabalho com diretivas e componentes. Eles não funcionam com outros tipos, como um serviço no seu caso. Dos documentos:

Um componente tem um ciclo de vida gerenciado pelo próprio Angular. Angular cria, renderiza, cria e renderiza seus filhos, verifica quando suas propriedades ligadas a dados são alteradas e as destroem antes de removê-lo do DOM.

As instâncias de diretiva e componente têm um ciclo de vida conforme o Angular as cria, atualiza e as destrói.

Sasxa
fonte
38
Então, basta mover minha ngOnInitlógica para o construtor de Injectableclasses? Lembrei-me de ler que você deve manter qualquer lógica fora do construtor por qualquer motivo.
Levi Fuller
48
@LeviFuller Sim, para serviços que você pode inicializar no construtor, ou melhor, criar o método init e chamá-lo do construtor (caso precise redefinir um serviço posteriormente).
Sasxa 31/01
9
Não exatamente, o OnInit tem a ver com a ligação. Você o usa quando deseja esperar que os valores de entrada sejam resolvidos, pois eles não estão disponíveis no construtor. O construtor pode ser chamado várias vezes. Por exemplo, quando você muda rota e carregar componentes diferentes que se "construídos" e destruiu cada vez ...
Sasxa
5
Também é importante notar aqui que os Sevices podem ser instanciados várias vezes, dependendo de onde você os inclui em providersmatrizes. Se você deseja um serviço singleton, coloque-o no módulo principal providerse, se desejar serviços por componente, adicione-os diretamente ao componente.
Askdesigners
4
Isso não é inteiramente incorreta, como @ SBD580 pontos em sua resposta, ngOnDestroyé chamado para serviços injetados
shusson
48

Não conheço todos os ganchos do ciclo de vida, mas quanto à destruição, ngOnDestroyna verdade , recebo o Injectable quando seu provedor é destruído (por exemplo, um Injectable fornecido por um componente).

De docs :

Gancho do ciclo de vida chamado quando uma diretiva, canal ou serviço é destruído.

Caso alguém esteja interessado em destruição, verifique esta pergunta:

SBD580
fonte
2
uma vergonha ngOnInit. Não é chamado :-( eu realmente queria fazer alguma mágica de inicialização atrasada transparente Se ngOnDestroypode ser chamado Eu não vejo por que o init não pode
Simon_Weaver
2

Nota: esta resposta se aplica apenas a componentes e diretivas angulares, NÃO a serviços.

Eu tive esse mesmo problema quando ngOnInit(e outros ganchos do ciclo de vida) não estavam disparando para meus componentes, e a maioria das pesquisas me levou até aqui.

O problema é que eu estava usando a sintaxe da função de seta ( =>) assim:

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

Aparentemente, isso não funciona no Angular 6. O uso de sintaxe de função que não seja da seta corrige o problema:

class MyComponent implements OnInit {
    public ngOnInit() {
        console.log("ngOnInit");
    }
}
AJ Richardson
fonte
Classes injetáveis ​​são serviços, não componentes. O OP pergunta sobre um serviço. Embora sua resposta possa estar correta em um POV de idioma, ela não responde a essa pergunta. Você deve excluí-lo.
Andrew Philips
@AndrewPhilips enquanto meu caso de uso é um pouco diferente do OP, uma pesquisa no Google por "ngOnInit não chamado" leva as pessoas aqui. Meu objetivo com esta resposta não é ajudar o OP, mas ajudar qualquer um dos mais de 70.000 espectadores que possam ter problemas semelhantes ngOnInit.
AJ Richardson
Justo. Acredito ter visto SO Q&A em que um autor pergunta e responde sua própria pergunta. Como um novo programador Angular, sua resposta teria me confundido duas semanas atrás. Tanto da perspectiva do SO quanto do NG, acho que sua resposta é digna de sua própria pergunta, portanto não foi excluída, mas "recategorizada". Quem sabe? Talvez isso atinja um público ainda mais amplo. Felicidades.
Andrew Philips
1
Faz sentido - editei minha resposta para deixar claro que isso não é para serviços.
AJ Richardson
0

Eu tive que chamar uma função depois que meu dataService foi inicializado, em vez disso, chamei dentro do construtor, que funcionou para mim.

Eduardo A EDUARDO Fernandez Di
fonte
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
fonte