ngOnInit не вызывается при создании класса Injectable


198

Почему не вызывается, ngOnInit()когда Injectableкласс разрешен?

Код

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

}

Консольный выход

FROM constructor()

Ответы:


314

Крючки жизненного цикла , как OnInit()работа с Директивами и Компонентами. Они не работают с другими типами, как сервис в вашем случае. Из документов:

Компонент имеет жизненный цикл, управляемый самой Angular. Angular создает его, отображает, создает и отображает его дочерние элементы, проверяет его, когда изменяются его свойства, связанные с данными, и уничтожает его перед удалением из DOM.

Директивы и экземпляры компонентов имеют жизненный цикл, так как Angular создает, обновляет и уничтожает их.


38
Так просто перенести мою ngOnInitлогику в конструктор для Injectableклассов? Я только что вспомнил, что читал, что по какой-то причине вы должны держать логику вне конструктора.
Леви Фуллер

48
@LeviFuller Да, для сервисов вы можете выполнить инициализацию в конструкторе или лучше создать метод init и вызвать его из конструктора (на случай, если вам потребуется сбросить сервис позже).
Саша

9
Не совсем, OnInit имеет отношение к связыванию. Вы используете его, когда хотите дождаться разрешения входных значений, так как они недоступны в конструкторе. Конструктор можно вызывать несколько раз. Например, когда вы меняете маршрут и загружаете разные компоненты, они каждый раз «конструируются» и разрушаются ...
Сасса

5
Также стоит отметить, что экземпляры Sevices могут создаваться несколько раз, в зависимости от того, где вы включили их в providersмассивы. Если вам нужен одноэлементный сервис, поместите его в основной модуль providers, а если вы хотите, чтобы сервисы для каждого компонента добавляли их непосредственно в компонент.
Askdesigners

4
Это не совсем неверно, так как @ SBD580 указывает в своем ответе на ngOnDestroyпризыв к инъекционным услугам
shusson

48

Я не знаю обо всех хуках жизненного цикла, но что касается уничтожения, ngOnDestroyфактически вызывается Injectable, когда уничтожается его поставщик (например, Injectable, предоставляемый компонентом).

Из docs :

Хук жизненного цикла, который вызывается при разрушении директивы, канала или службы .

Если кто-то заинтересован в уничтожении, проверьте этот вопрос:


2
такой позор ngOnInitне называется :-( Я действительно хотел сделать прозрачную магию отложенной инициализации. Если ngOnDestroyменя можно назвать, я не понимаю, почему init не может
Simon_Weaver

2

Примечание: этот ответ относится только к угловым компонентам и директивам, а НЕ к услугам.

У меня была такая же проблема, когда ngOnInit(и другие хуки жизненного цикла) не запускали мои компоненты, и большинство поисков привело меня сюда.

Проблема в том, что я использовал синтаксис функции стрелки ( =>) следующим образом:

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

По-видимому, это не работает в Angular 6. Использование синтаксиса функции без стрелки решает проблему:

class MyComponent implements OnInit {
    public ngOnInit() {
        console.log("ngOnInit");
    }
}

Инъекционные классы - это Сервисы, а не Компоненты. ОП спрашивает об услуге. Хотя ваш ответ может быть правильным от языка POV, он не отвечает на этот вопрос. Вы должны удалить его.
Эндрю Филипс

@AndrewPhilips, в то время как мой вариант использования немного отличается от OP, поиск в Google «ngOnInit not named» приводит людей сюда. Моя цель в этом ответе - не помочь ОП, а помочь любому из более 70 000 зрителей, у которых могут быть подобные проблемы ngOnInit.
AJ Ричардсон

Справедливо. Я считаю, что видел SO Q & A, в котором автор спрашивает, а затем отвечает на свой вопрос. Как новый программист на Angular, ваш ответ смутил бы меня две недели назад. Как с точки зрения SO, так и с точки зрения NG, я думаю, что ваш ответ достоин отдельного Вопроса, поэтому не удален, а «переклассифицирован». Кто знает? Возможно, это может охватить еще более широкую аудиторию. Приветствия.
Эндрю Филипс

1
Имеет смысл - я отредактировал свой ответ, чтобы понять, что это не для услуг.
AJ Ричардсон


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()


}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.