ngOnInit не викликається, коли клас Injectable миттєвий


197

Чому не 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()

Відповіді:


313

Гачки життєвого циклу , як OnInit()робота з директивами та компонентами. Вони не працюють з іншими типами, як, наприклад, сервіс у вашому випадку. З документів:

Компонент має життєвий цикл, яким керує сам Angular. Кутовий створює його, робить його, створює та робить його дітьми, перевіряє, коли його властивості, пов'язані з даними, змінюються та руйнують його, перш ніж видаляти його з DOM.

Екземпляри директив та компонентів мають життєвий цикл, оскільки Angular створює, оновлює та знищує їх.


38
Так просто перенесіть мою ngOnInitлогіку на конструктор для Injectableзанять? Я просто згадав, читаючи, що з будь-якої причини слід уникати будь-якої логіки від конструктора.
Леві Фуллер

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

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

5
Тут також варто зауважити, що сервіси можна екземплярувати кілька разів, залежно від того, де ви їх включите до providersмасивів. Якщо ви хочете одинарну службу, покладіть її в основний модуль providers, а якщо ви хочете, щоб однокомпонентні послуги додали їх безпосередньо до компонента.
Запитувальники

4
Це не зовсім неправильно, оскільки @ SBD580 у своїй відповіді ngOnDestroyзакликає вводити послуги з ін'єкціями
shusson

48

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

Від docs :

Гак життєвого циклу, який викликається при знищенні директиви, труби або служби .

Про всяк випадок, коли когось цікавить знищення, перевірте це питання:


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

2

Примітка: ця відповідь стосується лише кутових компонентів та директив, а не служб NOT.

У мене виникло те саме питання, коли 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, хоча мій випадок використання дещо відрізняється від ОП, пошук Google за "ngOnInit не називається" призводить людей сюди. Моя мета у цій відповіді - не допомогти ОП, а допомогти будь-якому з інших 70 000+ глядачів, у яких, можливо, є подібні проблеми ngOnInit.
AJ Річардсон

Досить справедливо. Я вважаю, що я бачив SO Q&A, в якому автор запитує, а потім відповідає на власне запитання. Як новий програмування Angular, ваша відповідь би бентежила мене два тижні тому. Як з точки зору ПС, так і з боку НГ, я вважаю, що ваша відповідь гідна власного запитання, тому не видаляється, а є "перекатегоризованою". Хто знає? Можливо, це може охопити ще ширшу аудиторію. Ура.
Ендрю Філіпс

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.