Cách chạy dịch vụ khi ứng dụng khởi động trong Angular 2


97

Tôi đã tạo một dịch vụ SocketService, về cơ bản nó khởi tạo socket để cho phép ứng dụng lắng nghe trên cổng. Dịch vụ này cũng tương tác với một số thành phần.

// socket.service.ts

export class SocketService {
    constructor() {
        // Initializes the socket
    }
    ...
}

Tôi biết mã trong hàm tạo của SocketService () chỉ bắt đầu chạy khi một thành phần sử dụng SocketService.

Và thường mã trong app.ts trông như thế này:

// app.ts

import {SocketService} from './socket.service';
...
class App {
    constructor () {}
}
bootstrap(App, [SocketService]);

Tuy nhiên, tôi muốn dịch vụ này chạy khi ứng dụng khởi động. Vì vậy, tôi đã tạo một mẹo, chỉ cần thêm hàm tạo private _socketService: SocketServicecủa App (). Vì vậy, bây giờ các mã trông như thế này:

// app.ts (mới)

import {SocketService} from './socket.service';
...
class App {
    constructor (private _socketService: SocketService) {}
}
bootstrap(App, [SocketService]);

Bây giờ nó hoạt động. Vấn đề là đôi khi các mã trong constructor () của SocketService chạy, đôi khi không. Vậy tôi phải làm như thế nào cho đúng? Cảm ơn


Hướng dẫn này đã giúp tôi: angle.io/docs/ts/latest/tutorial/…
Marian07

Câu trả lời:


130

Câu trả lời của Stuart đưa ra đúng hướng, nhưng không dễ tìm thông tin trên APP_INITIALIZER. Phiên bản ngắn là bạn có thể sử dụng nó để chạy mã khởi tạo trước khi chạy bất kỳ mã ứng dụng nào khác của bạn. Tôi đã tìm kiếm một lúc và tìm thấy những lời giải thích ở đâyđây , mà tôi sẽ tóm tắt trong trường hợp chúng biến mất khỏi web.

APP_INITIALIZER được định nghĩa trong góc / lõi. Bạn đưa nó vào app.module.ts của mình như thế này.

import { APP_INITIALIZER } from '@angular/core';

APP_INITIALIZER là một OpaqueToken (hoặc một InjectionToken kể từ Angular 4) tham chiếu đến dịch vụ ApplicationInitStatus. ApplicationInitStatus là một nhà cung cấp đa . Nó hỗ trợ nhiều phần phụ thuộc và bạn có thể sử dụng nó trong danh sách nhà cung cấp của mình nhiều lần. Nó được sử dụng như thế này.

@NgModule({
  providers: [
    DictionaryService,
    {
      provide: APP_INITIALIZER,
      useFactory: (ds: DictionaryService) => () => return ds.load(),
      deps: [DictionaryService],
      multi: true
    }]
})
export class AppModule { }

Khai báo trình cung cấp này cho lớp ApplicationInitStatus chạy phương thức DictionaryService.load (). load () trả về một lời hứa và ApplicationInitStatus chặn khởi động ứng dụng cho đến khi lời hứa đó được giải quyết. Hàm load () được định nghĩa như thế này.

load(): Promise<any> {
  return this.dataService.getDiscardReasons()
  .toPromise()
  .then(
    data => {
      this.dictionaries.set("DISCARD_REASONS",data);
    }
  )
}

Thiết lập như vậy từ điển sẽ được tải trước và các phần khác của ứng dụng có thể phụ thuộc vào từ điển một cách an toàn.

Chỉnh sửa: Hãy lưu ý rằng điều này sẽ làm tăng thời gian tải trước cho ứng dụng của bạn theo thời gian phương thức load () mất. Nếu bạn muốn tránh điều đó, bạn có thể sử dụng trình phân giải trên tuyến đường của mình.


Cảm ơn bạn vì điều này ... rất hữu ích
Gaurav Joshi

5
Đây phải là câu trả lời được chấp nhận. Hiện tại chỉ di chuyển một dòng mã từ một initphương thức khởi tạo sang một phương thức. Mặc dù các hàm tạo thực sự nên được giữ càng đơn giản càng tốt, nhưng chỉ suy nghĩ đó không làm cho nó trở thành một giải pháp thích hợp. Sử dụng APP_INITIALIZERkhông.
JP ten Berge

Tôi không nghĩ câu trả lời đã chọn là sai, vì nó giải quyết được vấn đề của OP. NHƯNG , vì tôi gặp một vấn đề tương tự trong quá trình phát triển của một số thư viện, tôi đã mở một câu hỏi khác mà câu trả lời này sẽ hoàn toàn phù hợp.
Machado

Cách tốt nhất để làm
Renil Babu

58

SocketServiceThay vào đó, hãy di chuyển logic trong hàm tạo của bạn sang một phương thức và sau đó gọi phương thức đó trong hàm tạo của thành phần chính của bạn hoặcngOnInit

SocketService

export class SocketService{
    init(){
        // Startup logic here
    }
}

Ứng dụng

import {SocketService} from './socket.service';
...
class App {
    constructor (private _socketService: SocketService) {
        _socketService.init();
    }
}
bootstrap(App, [SocketService]);

1
tôi không hiểu logic đằng sau làm những thứ gì trong phương thức thay vì hàm tạo, bạn có thể vui lòng giải thích điều này, lợi ích của việc làm logic trong phương thức là gì?
Pardeep Jain

1
Một cách tiếp cận sạch IMHO
inoabrian

12
Các trình xây dựng phải càng đơn giản càng tốt (thường chỉ có các điểm tiêm), trong trường hợp bạn cần thêm logic bổ sung, hãy sử dụng móc ngOnInit.
Sergio

1
Tuy nhiên, một điều khác mà nhóm không nghĩ đến .. Càng làm việc trên Angular 4, tôi nhận ra rằng khung Aurelia được xây dựng tuyệt vời như thế nào. Nó có tất cả các khả năng này ngay lập tức bằng cách chỉ cần thêm một người trang trí. Những người đó biết họ đang làm gì.
Joel Hernandez

1
@CodyBugstein Nó phụ thuộc vào trường hợp sử dụng của bạn. Nếu nó chỉ là fire-and-forget thì chỉ cần gọi phương thức async. Nếu bạn cần đợi kết quả, bạn có thể trả về một Promisetừ init()phương thức của mình và sau đó chuỗi nếu cần. Dù trường hợp nào nó cũng có thể được thực hiện, nhưng có lẽ sẽ khó và sẽ tùy thuộc vào bạn để giải quyết chi tiết. Nếu bạn cần trợ giúp thêm, bạn luôn có thể đăng câu hỏi với chi tiết về vấn đề chính xác của mình và cộng đồng sẽ sẵn lòng trợ giúp bạn.
SnareChops


1

Hãy thử Tạo phương thức khởi tạo dịch vụ và sau đó gọi nó trong ngOnInit () của thành phần của bạn.

  • Mô-đun dịch vụ

 export class SocketService {
    constructor() { }
        getData() {
            //your code Logic
        }
}

  • Thành phần

export class AppComponent {
    public record;  
    constructor(private SocketService: DataService){ }
    ngOnInit() {        
        this.SocketService.getData()
        .subscribe((data:any[]) => {
            this.record = data;
        });   
  }  
}       

Hi vọng điêu nay co ich.


1
@Hongbo muốn các dịch vụ chạy khi ứng dụng bắt đầu, không phải trong một thành phần đặc biệt được sử dụng dịch vụ
Jarod Moser

Câu trả lời thực sự đơn giản này đã làm việc cho tôi. Tôi thích những câu trả lời đơn giản. Cảm ơn.
Aggie Jon của 87
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.