Website-Suche

typescript - Wie man einen Dienst startet, wenn die App in Angular 2 startet


Ich habe einen Dienst SocketService erstellt, im Grunde initialisiert er den Socket, um der App zu ermöglichen, auf dem Port zu lauschen. Dieser Dienst interagiert auch mit einigen Komponenten.

// socket.service.ts

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

Ich weiß, dass der Code im Konstruktor von SocketService() erst zu laufen beginnt, wenn eine Komponente SocketService verwendet.

Und normalerweise sieht der Code in app.ts so aus:

// app.ts

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

Ich möchte jedoch, dass dieser Dienst beim Start der App ausgeführt wird. Also habe ich einen Trick angewendet, einfach private _socketService: SocketService im Konstruktor der App hinzuzufügen. Jetzt sieht der Code so aus:

// app.ts (neu)

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

Jetzt funktioniert es. Das Problem ist, dass der Code im Konstruktor von SocketService manchmal ausgeführt wird und manchmal nicht. Also, wie sollte ich es richtig machen?

Antwort #1

Stuarts Antwort weist in die richtige Richtung, aber es ist nicht einfach, Informationen über APP_INITIALIZER zu finden. Die Kurzversion ist, dass man es verwenden kann, um Initialisierungscode auszuführen, bevor irgendein anderer Anwendungscode ausgeführt wird. Ich habe eine Weile gesucht und Erklärungen hier und hier gefunden, die ich zusammenfassen werde, falls sie aus dem Internet verschwinden.

APP_INITIALIZER wird in angular/core definiert. Sie fügen es in Ihre app.module.ts wie folgt ein.

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

APP_INITIALIZER ist ein OpaqueToken (oder ein InjectionToken seit Angular 4), das auf den ApplicationInitStatus-Dienst verweist. ApplicationInitStatus ist ein Multi-Provider. Es unterstützt mehrere Abhängigkeiten und Sie können es in Ihrer Anbieter-Liste mehrfach verwenden. Es wird wie folgt verwendet.

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

Diese Provider-Deklaration sagt der ApplicationInitStatus-Klasse, die Methode DictionaryService.load() auszuführen. load() gibt ein Versprechen zurück und ApplicationInitStatus blockiert den App-Start, bis das Versprechen erfüllt wird. Die load()-Funktion ist wie folgt definiert.

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

Wenn es so eingerichtet ist, wird zuerst das Wörterbuch geladen und die anderen Teile der App können sich sicher darauf verlassen.

Bearbeiten: Beachten Sie, dass dies die anfängliche Ladezeit Ihrer App um die Zeit erhöhen wird, die die load()-Methode benötigt. Wenn Sie das vermeiden möchten, könnten Sie stattdessen einen Resolver in Ihrer Route verwenden.

Antwort #2

Verschieben Sie die Logik im Konstruktor Ihres SocketService in eine Methode und rufen Sie diese dann im Konstruktor Ihrer Hauptkomponente oder in ngOnInit auf

SocketService

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

App

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

Antwort #3

Siehe auch APP_INITIALIZER, das wie folgt beschrieben wird;

Eine Funktion, die ausgeführt wird, wenn eine Anwendung initialisiert wird.

Verwandte Artikel