Angular 4でのObservableオブジェクトの典型的な使用

Angular 4のコンポーネントとサービスのObservableオブジェクトの典型的なユースケースを紹介します。













ルーターパラメーターのサブスクライブと別のObservableへのマッピング



タスク: example.com/#/users/42



userId



ページを開くと、 userId



でユーザーデータを取得します。







解決策: UserDetailsComponent



コンポーネントを初期化するときに、ルーターのパラメーターをサブスクライブします。 つまり、 userId



が変更されると、サブスクリプションがuserId



ます。 受信したuserId



を使用して、 userService



サービスからのユーザーデータでObservable



を取得します。







 // UserDetailsComponent ngOnInit() { this.route.params .pluck('userId') //  userId   .switchMap(userId => this.userService.getData(userId)) .subscribe(user => this.user = user); }
      
      















ルーターパラメーターとクエリ文字列のサブスクライブ



タスク: example.com/#/users/42?regionId=13



load(userId, regionId)



ページを開くとき、 load(userId, regionId)



機能load(userId, regionId)



を実行する必要があります。 ルーターからuserId



を取得し、リクエストパラメーターからregionId



を取得します。







解決策:イベントのソースは2つあるため、 Observable.combineLatest関数を使用します。この関数は、各ソースがイベントを生成するときに起動します。







 ngOnInit() { Observable.combineLatest(this.route.params, this.route.queryParams) .subscribe(([params, queryParams]) => { //    const userId = params['userId']; const regionId = queryParams['regionId']; this.load(userId, regionId); }); }
      
      





ルーターに作成されたサブスクリプションは、オブジェクトが破棄されると削除されることに注意してください。角度はこれに従っているため、ルーターのパラメーターのサブスクリプションを解除する必要はありません。







ルーターは、提供するオブザーバブルを管理し、サブスクリプションをローカライズします。 コンポーネントが破壊されると、サブスクリプションはクリーンアップされ、メモリリークから保護されるため、ルートパラメーターObservableからサブスクリプションを解除する必要はありません。 マーク・レイコック


サブスクリプションの終了後にアニメーションの読み込みを停止します



タスク:データの保存を開始した後にダウンロードアイコンを表示し、データの保存時またはエラーが発生したときに非表示にします。







解決策: loading



変数はブートローダーの表示を担当し、ボタンをクリックした後、それをtrue



に設定しtrue



false



に設定するには、 Observable.finally



関数false



使用します。これらの関数は、サブスクリプションの完了後またはエラーが発生した場合に実行されます。







 save() { this.loading = true; this.userService.save(params) .finally(() => this.loading = false) .subscribe(user => { //   }, error => { //   }); }
      
      





独自のイベントソースを作成する



タスク: configService



lang$



変数を作成します。他のコンポーネントは、言語が変更されたときにサブスクライブして応答します。







解決策: BehaviorSubject



クラスを使用してlang$



変数を作成します。







BehaviorSubject



Subject



違い







  1. BehaviorSubject



    は初期値で初期化する必要があります。
  2. サブスクリプションは、 Subject



    aの最後の値を返します。
  3. getValue()



    関数を使用して、最後の値を直接取得できます。


lang$



変数を作成し、すぐに初期化します。 また、言語を設定するsetLang



関数を追加します。







 // configService lang$: BehaviorSubject<Language> = new BehaviorSubject<Language>(DEFAULT_LANG); setLang(lang: Language) { this.lang$.next(this.currentLang); //    }
      
      





コンポーネントの言語変更にサブスクライブします。 lang$



変数は、ホットなObservableオブジェクトです。つまり、オブジェクトが破棄されると、サブスクリプションはサブスクリプションを解除する必要があります。







 private subscriptions: Subscription[] = []; ngOnInit() { const langSub = this.configService.lang$ .subscribe(() => { // ... }); this.subscriptions.push(langSub); } ngOnDestroy() { this.subscriptions .forEach(s => s.unsubscribe()); }
      
      





takeUntilを使用して登録を解除する



特にコンポーネントに3つ以上のサブスクリプションがある場合、 よりエレガントなオプションでサブスクリプションを解除できます。







 private ngUnsubscribe: Subject<void> = new Subject<void>(); ngOnInit() { this.configService.lang$ .takeUntil(this.ngUnsubscribe) //    .subscribe(() => { // ... }); } ngOnDestroy() { this.ngUnsubscribe.next(); this.ngUnsubscribe.complete(); }
      
      





つまり、ホットサブスクリプションでメモリが失われないように、 ngUnsubscribe



の値が変更されるまでコンポーネントはngUnsubscribe



ます。 そして、ngOnDestroyがngOnDestroy



と変更さngOnDestroy



ます。 このオプションの利点は、各サブスクリプションに1行だけ追加すれば十分であり、サブスクリプションが時間どおりに機能することです。







オートコンプリートまたは検索にObservableを使用する



タスク:フォームにデータを入力するときにページの提案を表示する







解決策:フォームデータを変更するためにサブスクライブし、変更する入力データのみを取得し、イベントが多すぎないように少し遅延させて、Wikipediaにリクエストを送信します。 結果はコンソールに表示されます。 興味深い点は、新しいデータswitchMap



場合にswitchMap



が以前の要求をキャンセルswitchMap



です。 たとえば、最後から2番目のリクエストが2秒間実行され、最後の0.2秒間実行された場合、最後のリクエストの結果がコンソールに表示されます。







 ngOnInit() { this.form.valueChanges .takeUntil(this.ngUnsubscribe) //    .map(form => form['search-input']) //   .distinctUntilChanged() //    .debounceTime(300) //    .switchMap(this.wikipediaSearch) //  Observable     .subscribe(data => console.log(data)); } wikipediaSearch = (text: string) => { return Observable .ajax('https://api.github.com/search/repositories?q=' + text) .map(e => e.response); }
      
      





リクエストのキャッシュ



タスク: Observableリクエストをキャッシュする必要があります。







解決策: publishReplay



refCount



束を使用します。 最初の関数は1つの関数値を2秒間キャッシュし、2番目の関数は作成されたサブスクリプションをカウントします。 つまり、すべてのサブスクリプションが完了すると、Observableは終了します。 ここでもっと読むことができます。







 // tagService private tagsCache$ = this.getTags() .publishReplay(1, 2000) //     2  .refCount() //   .take(1); //  1  getCachedTags() { return tagsCache$; }
      
      





シリアルコンバイン



タスク:サーバー上の重大な状況! バックエンドチームは、製品の正しい更新のために厳密に順番に実行する必要があると述べました。







  1. 製品データ(タイトルと説明)の更新。
  2. 製品タグのリストを更新します。
  3. 製品カテゴリのリストを更新します。


解決策: productService



から派生した3つのObservableがproductService



ます。 concatMap



を使用しconcatMap









 const updateProduct$ = this.productService.update(product); const updateTags$ = this.productService.updateTags(productId, tagList); const updateCategories$ = this.productService.updateCategories(productId, categoryList); Observable .from([updateProduct$, updateTags$, updateCategories$]) .concatMap(a => a) //    .toArray() //     .subscribe(res => console.log(res)); // res    
      
      





スタッフのなぞなぞ



少し練習したい場合は、前の問題を解決しますが、製品を作成します。 つまり、最初に製品を作成し、次にタグを更新してから、カテゴリのみを更新します。







便利なリンク






All Articles