ngOnInit no se llama cuando se instancia la clase Inyectable

197

¿Por qué no se ngOnInit()llama cuando Injectablese resuelve una clase?

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

}

Salida de la consola

FROM constructor()
Levi Fuller
fuente

Respuestas:

312

Ganchos de ciclo de vida , como OnInit()trabajar con Directivas y Componentes. No funcionan con otros tipos, como un servicio en su caso. De documentos:

Un componente tiene un ciclo de vida administrado por Angular. Angular lo crea, lo representa, crea y representa sus elementos secundarios, lo comprueba cuando cambian sus propiedades vinculadas a datos y lo destruye antes de eliminarlo del DOM.

Las instancias de directivas y componentes tienen un ciclo de vida a medida que Angular las crea, actualiza y destruye.

Sasxa
fuente
38
Entonces, ¿simplemente muevo mi ngOnInitlógica al constructor de Injectableclases? Acabo de recordar haber leído que deberías mantener cualquier lógica fuera del constructor por cualquier razón.
Levi Fuller
48
@LeviFuller Sí, para los servicios puede hacer la inicialización en el constructor, o mejor hacer el método init y llamarlo desde el constructor (en caso de que necesite restablecer un servicio más adelante).
Sasxa
9
No exactamente, OnInit tiene que ver con el enlace. Lo usa cuando desea esperar a que se resuelvan los valores de entrada, ya que no están disponibles en el constructor. Se puede llamar al constructor varias veces. Por ejemplo, cuando cambia la ruta y carga diferentes componentes, se "construyen" y se destruyen cada vez ...
Sasxa
55
También vale la pena señalar aquí que los servicios se pueden instanciar varias veces, dependiendo de dónde los incluya en las providersmatrices. Si desea un servicio singleton, colóquelo en el módulo principal providersy si desea servicios por componente, agréguelos directamente al componente.
Askdesigners
44
Esto no es del todo incorrecto, ya que @ SBD580 señala en su respuesta, ngOnDestroyse llama para servicios inyectados
shusson
48

No conozco todos los ganchos del ciclo de vida, pero en cuanto a la destrucción, ngOnDestroy realidad me llaman Injectable cuando se destruye su proveedor (por ejemplo, un Injectable suministrado por un componente).

Desde el docs :

Gancho de ciclo de vida que se llama cuando se destruye una directiva, tubería o servicio .

En caso de que alguien esté interesado en la destrucción, revise esta pregunta:

SBD580
fuente
2
tal vergüenza ngOnInitno se llama :-( Realmente quería hacer algo de magia de inicialización retrasada transparente. Si ngOnDestroyse puede llamar, no veo por qué init no puede
Simon_Weaver
2

Nota: esta respuesta se aplica solo a componentes y directivas angulares, NO a servicios.

Tuve este mismo problema cuando ngOnInit (y otros ganchos del ciclo de vida) no estaban activando mis componentes, y la mayoría de las búsquedas me llevaron aquí.

El problema es que estaba usando la sintaxis de la función de flecha ( =>) así:

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

Aparentemente, eso no funciona en Angular 6. El uso de la sintaxis de la función sin flecha soluciona el problema:

class MyComponent implements OnInit {
    public ngOnInit() {
        console.log("ngOnInit");
    }
}
AJ Richardson
fuente
Las clases inyectables son servicios, no componentes. OP pregunta por un servicio. Aunque su respuesta puede ser correcta desde un punto de vista de idioma, no responde esta pregunta. Deberías eliminarlo.
Andrew Philips
@AndrewPhilips, mientras que mi caso de uso es ligeramente diferente de los OP, una búsqueda en Google de "ngOnInit no llamado" lleva a la gente aquí. Mi objetivo con esta respuesta no es ayudar al OP, sino ayudar a cualquiera de los más de 70,000 espectadores que puedan tener problemas similares ngOnInit.
AJ Richardson
Lo suficientemente justo. Creo que he visto SO Q&A en las que un autor pregunta y luego responde a su propia pregunta. Como nuevo programador angular, su respuesta me habría confundido hace dos semanas. Tanto desde una perspectiva SO como NG, creo que su respuesta es digna de su propia pregunta, por lo que no se elimina sino que se "recategoriza". ¿Quién sabe? Quizás podría llegar a un público aún más amplio. Salud.
Andrew Philips
1
Tiene sentido: edité mi respuesta para dejar en claro que esto no es para servicios.
AJ Richardson
0

Tuve que llamar a una función una vez que se inicializó mi dataService, en su lugar, lo llamé dentro del constructor, eso funcionó para mí.

Eduardo A EDUARDO Fernández Di
fuente
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
fuente