ngOnInit không được gọi khi lớp Tiêm được khởi tạo


196

Tại sao không ngOnInit()được gọi khi một Injectablelớp được giải quyết?

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

}

Bảng điều khiển đầu ra

FROM constructor()

Câu trả lời:


312

Móc vòng đời , như OnInit()làm việc với Chỉ thị và Thành phần. Họ không làm việc với các loại khác, như một dịch vụ trong trường hợp của bạn. Từ tài liệu:

Một Thành phần có vòng đời được quản lý bởi chính Angular. Angular tạo ra nó, kết xuất nó, tạo và kết xuất các con của nó, kiểm tra nó khi các thuộc tính ràng buộc dữ liệu của nó thay đổi và phá hủy nó trước khi xóa nó khỏi DOM.

Các trường hợp chỉ thị và thành phần có vòng đời khi Angular tạo, cập nhật và phá hủy chúng.


38
Vì vậy, chỉ cần di chuyển ngOnInitlogic của tôi để xây dựng cho Injectablecác lớp? Tôi chỉ nhớ đọc rằng bạn nên giữ bất kỳ logic nào ra khỏi hàm tạo vì bất kỳ lý do gì.
Levi Fuller

48
@LeviFuller Yea, đối với các dịch vụ bạn có thể thực hiện khởi tạo trong hàm tạo hoặc tốt hơn là tạo phương thức init và gọi nó từ hàm tạo (trong trường hợp bạn cần đặt lại dịch vụ sau).
Sasxa

9
Không chính xác, OnInit phải làm với ràng buộc. Bạn sử dụng nó khi bạn muốn đợi các giá trị đầu vào được giải quyết, vì chúng không có sẵn trong hàm tạo. Con constructor có thể được gọi nhiều lần. Ví dụ: khi bạn thay đổi tuyến đường và tải các thành phần khác nhau, chúng sẽ bị "xây dựng" và bị phá hủy mỗi lần ...
Sasxa

5
Điều đáng chú ý ở đây là Dịch vụ có thể được khởi tạo nhiều lần, tùy thuộc vào nơi bạn đưa chúng vào providersmảng. Nếu bạn muốn một dịch vụ đơn lẻ, hãy đặt nó vào mô-đun chính của bạn providersvà nếu bạn muốn các dịch vụ theo từng thành phần hãy thêm chúng vào thành phần trực tiếp.
Người hỏi

4
Điều này không hoàn toàn không chính xác, vì @ SBD580 điểm trong câu trả lời của anh ta, ngOnDestroyđược kêu gọi cho các dịch vụ được tiêm
shusson

48

Tôi không biết về tất cả các móc vòng đời, nhưng đối với sự phá hủy, ngOnDestroythực sự được gọi là Tiêm khi nhà cung cấp của nó bị phá hủy (ví dụ: Thuốc tiêm được cung cấp bởi một thành phần).

Từ docs :

Móc vòng đời được gọi khi chỉ thị, đường ống hoặc dịch vụ bị phá hủy.

Chỉ trong trường hợp bất cứ ai quan tâm đến việc phá hủy hãy kiểm tra câu hỏi này :


2
thật xấu hổ ngOnInitkhông được gọi là :-( Tôi thực sự muốn thực hiện một số phép thuật khởi tạo bị trì hoãn trong suốt. Nếu ngOnDestroycó thể được gọi tôi không hiểu tại sao init không thể
Simon_Weaver

3

Lưu ý: câu trả lời này chỉ áp dụng cho các thành phần và chỉ thị của Angular, KHÔNG phải dịch vụ.

Tôi gặp vấn đề tương tự khi ngOnInit(và các móc vòng đời khác) không bắn cho các thành phần của tôi và hầu hết các tìm kiếm đã dẫn tôi đến đây.

Vấn đề là tôi đã sử dụng cú pháp hàm mũi tên ( =>) như thế này:

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

Rõ ràng là không hoạt động trong Angular 6. Sử dụng cú pháp hàm không mũi tên sẽ khắc phục vấn đề:

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

Các lớp thuốc tiêm là Dịch vụ, không phải Thành phần. OP hỏi về một Dịch vụ. Mặc dù câu trả lời của bạn có thể đúng từ một ngôn ngữ POV, nhưng nó không trả lời câu hỏi này. Bạn nên xóa nó.
Andrew Philips

@AndrewPhilips trong khi trường hợp sử dụng của tôi hơi khác so với OP, một tìm kiếm google cho "ngOnInit không được gọi" dẫn mọi người đến đây. Mục tiêu của tôi với câu trả lời này không phải là để giúp OP, mà là giúp bất kỳ ai trong số hơn 70.000 người xem khác có thể có vấn đề tương tự ngOnInit.
AJ Richardson

Đủ công bằng. Tôi tin rằng tôi đã xem SO Q & A trong đó một tác giả hỏi và sau đó trả lời câu hỏi của chính họ. Là một lập trình viên Angular mới, câu trả lời của bạn sẽ làm tôi bối rối hai tuần trước. Cả hai từ góc độ SO và NG, tôi nghĩ rằng câu trả lời của bạn xứng đáng với Câu hỏi của chính nó, vì vậy không bị xóa nhưng đã phân loại lại. Ai biết? Có lẽ nó có thể đạt đến một đối tượng thậm chí rộng hơn. Chúc mừng.
Andrew Philips

1
Có ý nghĩa - Tôi đã chỉnh sửa câu trả lời của mình để làm rõ rằng đây không phải là dịch vụ.
AJ Richardson

0

Tôi đã phải gọi một hàm khi dataService của tôi được khởi tạo, thay vào đó, tôi gọi nó bên trong hàm tạo, nó hoạt động với tôi.


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


}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.