Injectableクラスがインスタンス化されるときにngOnInitが呼び出されない


196

クラスが解決さ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()

回答:


312

ライフサイクルフックOnInit()ディレクティブやコンポーネントでの作業など。これらは、サービスのような他のタイプでは機能しません。ドキュメントから:

コンポーネントには、Angular自体が管理するライフサイクルがあります。Angularはそれを作成し、レンダリングし、その子を作成してレンダリングし、データにバインドされたプロパティが変更されたときにチェックし、DOMから削除する前に破棄します。

ディレクティブとコンポーネントインスタンスは、Angularがインスタンスを作成、更新、破棄するときにライフサイクルを持ちます。


38
では、ngOnInitロジックをInjectableクラスのコンストラクターに移動するだけですか?なんらかの理由でコンストラクターからロジックを除外する必要があることを読んだことを思い出しました。
Levi Fuller

48
@LeviFullerええ、サービスの場合は、コンストラクタで初期化を行うか、initメソッドを作成してコンストラクタから呼び出すことができます(後でサービスをリセットする必要がある場合)。
Sasxa 2016年

9
厳密には、OnInitはバインディングに関係しています。コンストラクターでは使用できないため、入力値が解決されるまで待機する場合に使用します。コンストラクターは複数回呼び出すことができます。たとえば、ルートを変更してさまざまなコンポーネントをロードすると、それらは毎回「構築」されて破壊されます...
Sasxa

5
また、配列内のどこに含めるかによって、サービスを複数回インスタンス化できることにも注意してくださいproviders。シングルトンサービスが必要な場合は、メインモジュールのに配置しproviders、コンポーネントごとのサービスが必要な場合は、コンポーネントに直接追加します。
Askdesigners 2017

4
@ SBD580が彼の回答で指摘しているように、これは完全に間違っているわけではありません。ngOnDestroy注入されたサービスに対して呼び出されます
shusson

48

すべてのライフサイクルフックについては知りませんが、破棄については、ngOnDestroyプロバイダーが破棄されたときにInjectable で実際に呼び出されます(たとえば、コンポーネントによって提供されたInjectable)。

から docs :

ディレクティブ、パイプ、またはサービスが破棄されたときに呼び出されるライフサイクルフック。

誰かが破壊に興味がある場合に備えて、この質問をチェックしてください:


2
そのような恥ngOnInitは呼ばれません:-(私は本当にいくつかの透過的な遅延初期化の魔法をやりたかったです。ngOnDestroy呼び出すことができれば、なぜinitができないのか
わかり

3

注:この回答はAngularコンポーネントとディレクティブにのみ適用され、サービスには適用されません。

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");
    }
}

注入可能なクラスはサービスであり、コンポーネントではありません。OPはサービスについて尋ねます。あなたの答えは言語の視点から正しいかもしれませんが、この質問には答えません。削除してください。
Andrew Philips、

@AndrewPhilips私の使用例はOPの使用例とは少し異なりますが、「ngOnInit not called」のグーグル検索はここの人々を導きます。この回答の私の目標は、OPを支援することではなく、で同様の問題を抱えている可能性がある他の70,000人以上の視聴者を支援することですngOnInit
AJリチャードソン

けっこうだ。筆者が自分の質問に答えた後のSO Q&Aを見たことがあると思います。新しいAngularプログラマーとして、あなたの答えは2週間前に私を混乱させたでしょう。SOとNGの両方の観点から、あなたの答えはそれ自体の質問に値するので、削除せずに「再分類」します。知るか?多分それはさらに広い聴衆に届くかもしれません。乾杯。
Andrew Philips、

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


}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.