アプリがAngular2で起動したときにサービスを実行する方法


99

私はサービスSocketServiceを作成しました。基本的には、アプリがポートでリッスンできるようにソケットを初期化します。このサービスは、一部のコンポーネントとも相互作用します。

// socket.service.ts

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

SocketServiceのconstructor()のコードは、コンポーネントがSocketServiceを使用するときにのみ実行を開始することを知っています。

そして通常、app.tsのコードは次のようになります。

// app.ts

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

ただし、アプリの起動時にこのサービスを実行したいと思います。そこでprivate _socketService: SocketService、アプリのコンストラクター()を追加するだけでトリックを作成しました。したがって、コードは次のようになります。

// app.ts(新規)

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

今では動作します。問題は、SocketServiceのconstructor()のコードが実行されることもあれば、実行されないこともあります。では、どうすれば正しく行うことができますか?ありがとう


このガイドでは、私を支援してきました:angular.io/docs/ts/latest/tutorial/...を
Marian07

回答:


134

スチュアートの答えは正しい方向を示していますが、APP_INITIALIZERに関する情報を見つけるのは簡単ではありません。短いバージョンでは、他のアプリケーションコードを実行する前に、これを使用して初期化コードを実行できます。しばらく検索して、ここここで説明を見つけました。それらがWebから消えた場合に備えて要約します。

APP_INITIALIZERは角度/コアで定義されています。このようにapp.module.tsに含めます。

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

APP_INITIALIZERは、ApplicationInitStatusサービスを参照するOpaqueToken(またはAngular 4以降のInjectionToken)です。ApplicationInitStatusはマルチプロバイダーです。複数の依存関係をサポートしており、プロバイダーリストで複数回使用できます。このように使われます。

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

このプロバイダー宣言は、ApplicationInitStatusクラスにDictionaryService.load()メソッドを実行するように指示します。load()はpromiseを返し、ApplicationInitStatusはpromiseが解決されるまでアプリの起動をブロックします。load()関数はこのように定義されています。

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

辞書が最初に読み込まれ、アプリの他の部分が安全に辞書に依存できるように設定します。

編集:これにより、load()メソッドにかかる時間がどれだけ長くても、アプリの先行読み込み時間が長くなることに注意してください。それを避けたい場合は、代わりにルートでリゾルバーを使用できます。


これをありがとう...非常に役に立ちました
Gaurav Joshi 2017

5
これは受け入れられた答えでなければなりません。現在のものは、コンストラクターからinitメソッドに1行のコードのみを移動します。コンストラクターは確かに可能な限り単純に保つ必要がありますが、その考えだけでは適切な解決策にはなりません。を使用APP_INITIALIZERします。
JP ten Berge 2018

OPの問題を解決するので、選択した答えが間違っているとは思いません。しかし、私はいくつかのライブラリの開発に同様の問題を抱えているように、私はopennedてきた別の質問この答えは完全に収まるようにします。
マチャド

最善の方法
RenilBabu19年

58

SocketService代わりに、コンストラクターのロジックをメソッドに移動してから、メインコンポーネントのコンストラクターでそれを呼び出すか、ngOnInit

SocketService

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

アプリ

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

1
コンストラクターの代わりにメソッドの背後にあるロジックが何をするのかわかりません。これを説明してください。メソッドでロジックを実行する利点は何ですか?
Pardeep Jain 2016

1
クリーナーアプローチ私見
inoabrian

12
ロジックを追加する必要がある場合は、ngOnInitフックを使用して、コンストラクターをできるだけ単純にする必要があります(通常はインジェクションポイントのみ)。
セルジオ

1
チームが考えていなかったさらに別のこと..Angular4に取り組むほど、Aureliaフレームワークがいかに見事に構築されているかがわかります。デコレータを追加するだけで、箱から出してすぐにこれらすべての可能性があります。それらの人は彼らが何をしているのか知っています。
Joel Hernandez

1
@CodyBugsteinユースケースによって異なります。ファイアアンドフォーゲットの場合は、asyncメソッドを呼び出すだけです。結果を待つ必要がある場合Promiseは、init()メソッドからを返し、必要に応じてチェーンすることができます。いずれにせよ、それは可能ですが、おそらく困難であり、詳細を理解するのはあなた次第です。さらにサポートが必要な場合は、いつでも正確な問題の詳細を記載した質問を投稿できます。コミュニティが喜んでお手伝いします。
snareChops 2018年


1

サービスコンストラクターを作成してから、コンポーネントのngOnInit()で呼び出してみてください。

  • サービスモジュール

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

  • 成分

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

お役に立てれば。


1
@Hongboは、サービスを使用している特定のコンポーネントではなく、アプリの起動時にサービスを実行することを望んでいます
Jarod Moser 2016

この本当に簡単な答えは私のために働いた。簡単な答えが大好きです。ありがとう。
87の
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.