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

ระยะเวลาการใช้งาน hooksเช่นOnInit()ทำงานกับ Directives and Components มันไม่ทำงานกับประเภทอื่น ๆ เช่นบริการในกรณีของคุณ จากเอกสาร:

Component มีวงจรชีวิตที่จัดการโดย Angular เอง Angular สร้างมันแสดงผลสร้างและสร้างลูก ๆ ของมันตรวจสอบเมื่อคุณสมบัติที่ผูกกับข้อมูลเปลี่ยนแปลงและทำลายก่อนที่จะลบออกจาก DOM

อินสแตนซ์ Directive และคอมโพเนนต์มีวงจรชีวิตเมื่อ Angular สร้างอัปเดตและทำลายมัน


38
ดังนั้นเพียงแค่ย้ายngOnInitตรรกะของฉันไปที่ตัวสร้างสำหรับInjectableชั้นเรียน? ฉันเพิ่งจำการอ่านที่คุณควรป้องกันตรรกะใด ๆ ออกจากนวกรรมิกด้วยเหตุผลใดก็ตาม
Levi Fuller

48
@LeviFuller ใช่แล้วสำหรับบริการที่คุณสามารถทำการกำหนดค่าเริ่มต้นใน Constructor หรือสร้างเมธอด init ให้ดีขึ้นและเรียกมันจาก Constructor (ในกรณีที่คุณต้องการรีเซ็ตบริการในภายหลัง)
Sasxa

9
ไม่อย่างแน่นอนOnInitเกี่ยวข้องกับการผูกมัด คุณใช้มันเมื่อคุณต้องการรอให้ค่าอินพุตถูกแก้ไขเนื่องจากไม่มีอยู่ในตัวสร้าง คอนสตรัคเตอร์สามารถเรียกได้หลายครั้ง ตัวอย่างเช่นเมื่อคุณเปลี่ยนเส้นทางและโหลดส่วนประกอบที่แตกต่างกันพวกเขาจะได้ "สร้าง" และทำลายทุกครั้ง ...
Sasxa

5
นอกจากนี้ยังเป็นที่น่าสังเกตว่าที่ Sevices สามารถสร้างอินสแตนซ์ได้หลายครั้งขึ้นอยู่กับว่าคุณใส่ไว้ที่ไหนในprovidersอาร์เรย์ หากคุณต้องการบริการแบบซิงเกิลให้ใส่ไว้ในโมดูลหลักของคุณprovidersและถ้าคุณต้องการบริการแบบองค์ประกอบต่อเพิ่มให้กับองค์ประกอบโดยตรง
Askdesigners

4
สิ่งนี้ไม่ถูกต้องทั้งหมดเนื่องจาก @SBD580 คะแนนในคำตอบของเขาngOnDestroyถูกเรียกใช้สำหรับบริการที่ฉีด
shusson

48

ฉันไม่รู้เกี่ยวกับวงจรชีวิตทั้งหมด แต่เกี่ยวกับการทำลาย ngOnDestroyจริง ๆ แล้วถูกเรียกใช้งาน Injectable เมื่อผู้ให้บริการถูกทำลาย (ตัวอย่างเช่น Injectable ที่จัดหาโดยส่วนประกอบ)

จาก docs :

เบ็ดวงจรชีวิตที่เรียกว่าเมื่อคำสั่งท่อหรือบริการถูกทำลาย

ในกรณีที่ใครสนใจเช็คทำลายคำถามนี้ :


2
ดังกล่าวเป็นความอัปยศngOnInit. ไม่ได้เรียกว่า :-( ผมอยากจะทำบางอย่างโปร่งใสมายากลเริ่มต้นล่าช้าหากngOnDestroyสามารถเรียกได้ว่าผมไม่เห็นเหตุผลที่ไม่สามารถ init
Simon_Weaver

2

หมายเหตุ: คำตอบนี้ใช้ได้กับส่วนประกอบและคำสั่งของ 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 ถามเกี่ยวกับบริการ แม้ว่าคำตอบของคุณอาจถูกต้องจากภาษา POV แต่ก็ไม่ได้ตอบคำถามนี้ คุณควรลบทิ้ง
Andrew Philips

@AndrewPhilips ในขณะที่กรณีการใช้งานของฉันแตกต่างจาก OP ของเล็กน้อยการค้นหาโดย Google สำหรับ "ngOnInit ไม่เรียกว่า" ทำให้คนที่นี่ เป้าหมายของฉันกับคำตอบนี้ไม่ได้เพื่อช่วยให้ OP แต่จะช่วยให้การใด ๆ ของอื่น ๆ 70,000 ngOnInitผู้ชมที่อาจจะมีปัญหาที่คล้ายกันกับ
AJ Richardson

ยุติธรรมพอสมควร ฉันเชื่อว่าฉันเคยเห็น SO Q&A ที่ผู้เขียนถามแล้วตอบคำถามของตนเอง ในฐานะโปรแกรมเมอร์ Angular คนใหม่คำตอบของคุณจะทำให้ฉันสับสนเมื่อสองสัปดาห์ก่อน ทั้งจากมุมมอง SO และ NG ฉันคิดว่าคำตอบของคุณมีค่าสำหรับคำถามของตัวเองดังนั้นอย่าลบ แต่ "จัดหมวดหมู่" ใครจะรู้? บางทีมันอาจเข้าถึงผู้ชมที่กว้างขึ้น ไชโย
Andrew Philips

1
เหมาะสม - ฉันแก้ไขคำตอบของฉันเพื่อให้ชัดเจนว่านี่ไม่ใช่การบริการ
AJ Richardson


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.