Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
840 views
in Technique[技术] by (71.8m points)

typescript - How to run a service when the app starts in Angular 2

I created a service SocketService, basically it initializes the socket to let the app listen on the port. This service also interacts with some components.

// socket.service.ts

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

I know the code in SocketService's constructor() only starts to run when a component use SocketService.

And usually the code in app.ts looks like this:

// app.ts

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

However, I want this service run when the app starts. So I made a trick, just add private _socketService: SocketService in App's constructor(). So now the codes look like this:

// app.ts (new)

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

Now it works. The problem is sometimes the codes in SocketService's constructor() run, sometimes not. So how should I do it correctly? Thanks

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Stuart's answer points in the right direction, but it's not easy to find information on APP_INITIALIZER. The short version is you can use it to run initialization code before any of your other application code runs. I searched for a while and found explanations here and here, which I will summarize in case they disappear from the web.

APP_INITIALIZER is defined in angular/core. You include it in your app.module.ts like this.

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

APP_INITIALIZER is an OpaqueToken (or an InjectionToken since Angular 4) that references the ApplicationInitStatus service. ApplicationInitStatus is a multi provider. It supports multiple dependencies and you can use it in your providers list multiple times. It is used like this.

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

This provider declaration tells the ApplicationInitStatus class to run the DictionaryService.load() method. load() returns a promise and ApplicationInitStatus blocks the app startup until the promise resolves. The load() function is defined like this.

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

Set up like that the dictionary gets loaded first and the other parts of the app can safely depend on it.

Edit: Be aware that this will increase the up-front load time for you app by however long the load() method takes. If you want to avoid that you could use a resolver on your route instead.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
...