Angular - detecting when two subscriptions have updated

江枫思渺然 提交于 2019-12-08 07:47:04

问题


In a component, in ngOnInit() I've got two subscriptions to a data service. I want to do some processing once both subscriptions have returned. Whats the best way to do this? I can just process at the end of each, this just seems a little inefficient and won't work for which ever subscription activates first,

Thanks,

Component.TS

ngOnInit()
{
  this.dataService.dataA().subscribe((dataAJSON) => 
 {
   this.dataA= dataAJSON
 }

 this.dataService.dataB().subscribe((dataBJSON) => 
 {
   this.dataB= dataBJSON
 }

DataService

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/map';

@Injectable()

export class PMDataService
{
  constructor(public http : Http)
  {

  }

  dataA()
  {

    var dataA: any;
    var json;

    dataA= this.http.get("./assets/dataa.json")
      .map(res => res.json());

    return dataA
  }

  dataB()
  {

    var dataB: any;
    var json;

    dataB= this.http.get("./assets/datab.json")
      .map(res => res.json());

    return dataB
  }

}

回答1:


You can use Observable#forkJoin function on the Observables. It emits the last value from each when all observables complete,

Observable.forkJoin(this.dataService.dataA(), this.dataService.dataB())
          .subscribe(val => /* val is an array */)



回答2:


The method used depends on how you want to receive the data:

You can use the zip function. Emits once when all have emitted once. So similar to Promise.all except not on completion.

Observable.zip(obs1, obs2).subscribe((val) => { ... });

You can use the forkJoin function. Emits once when all have completed. So exactly like Promise.all.

Observable.forkJoin(obs1, obs2).subscribe((val) => { ... });

You can use the merge function. Emits in order of emission so could be 1st then 2nd or 2nd then 1st:

obs1.merge(obs2).subscribe((val) => { ... });

You can use concat function. Emits in order 1st then 2nd regardless if 2nd emits first:

obs1.concat(obs2).subscribe((val) => { ... });

It's best practice to split these up into a couple lines for clarity.

const obs1 = Rx.Observable.of(1,2,3);
const obs2 = Rx.Observable.of(1,2,3);
const example = Observable.zip(obs1, obs2);
//const example = Observable.forkJoin(obs1, obs2);
//const example = obs1.merge(obs2);
//const example = obs1.concat(obs2);
example.subscribe(val => { ... });



回答3:


You could use the operator Zip or CombineLatest from rxjs.

See ReactiveX operators

You could do something like this:

    Observable.zip(
        this.http.get("./assets/dataa.json"),
        this.http.get("./assets/dataa.json")
    .take(1)
    .map(values => [values[0].json(), values[1].json()])
    .subscribe(values => {
        // do something with my values
    });



回答4:


You could You can use concat to combine the observables and return a single observable.

Subscribe to observables in order as previous completes, emit values

changed service code

import 'rxjs/add/operator/concat';

export class PMDataService
{
  data(){
    return this.dataA().concat(this.dataB());
  }
  // methods dataA and dataB are unchanged, some of the constructor
}

Component code

ngOnInit(){
  this.dataService.data().subscribe((dataJSON) => 
     {
       this.dataA= dataAJSON[0];
       this.dataB= dataAJSON[1];
     }
}


来源:https://stackoverflow.com/questions/47338271/angular-detecting-when-two-subscriptions-have-updated

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!