2

The scenario is , there is a single service(json-data-service.ts) having a method getWebservicedata() which returns http.post(url) ie it makes an ajax call when method is called. I have different components like(pie-chart-components,bar-chart-component, line-chart components etc) and they all created at the same time on a single page. They all have their different metadata(clientJson) and a single observable.

Is there any way, by which we can make a single ajax request by multiple components parallely.

In other words, is there any way such that before ajax request is executed, it takes all the metadata from different components(PieComponent.ts,LineComponent.ts etc) and fetch data from the same url for different metadata(clientJson) of different components, at the same time parallely?

json-data-service.ts

    getSolrData(clientJson): Observable<JsonData[]> {
    console.log('Retriving Data from Solr Server.......' + JSON.stringify(clientJson));
    let headers = new Headers({ 'Content-Type': 'application/json' });
    let options = new RequestOptions({ headers: headers });
    let url = "http://183.82./PI3_Sor_WebSer/solrSe"; 
    return this.http.post(url, clientJson).map((res: Response) => res.json());
  }

pie-chart.component.ts

initData() {

    let clientJson = {
      "aoId": "M_AO_918","viewBys": ["usstate"]----------------- };

    this.jsonDataService.getSolrData(clientJson).subscribe(
      success => this.buildPieChart(success),
      error => this.errorMessage = error
    );
  }
  buildPieChart(jsonData) {
-----------
}

line-chart.component.ts

initData() {

    let clientJson = {
      "aoId": "M_AO_918","viewBys": ["brands"]----------------- };

    this.jsonDataService.getSolrData(clientJson).subscribe(
      success => this.buildlineChart(success),
      error => this.errorMessage = error
    );
  }
  buildlineChart(jsonData) {
-----------
}
  • here, in clientJson , "viewbys" and similarly other data are different, –  Jun 30 '17 at 07:12

1 Answers1

2

You want something using the rxjs .share() method (https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/share.md). Basically it allows multiple subscribers to share the same observable sequence.

export class Service {
  observableShare: Observable<string>; // store the shared observable
  
  constructor(private http: Http){}
  
  getData(){
    if(this.observableShare){ // if api is still processing, return shared observable
        return this.observableShare;
    }else{ // else api has not started, start api and return shared observable
      this.observableShare = this.http.post('url')
        .map(res => res.json())
        .share(); // share observable sequence among multiple subscribers
      
      return this.observableShare;
    }
    
  }
}

Here is a working plunkr (https://plnkr.co/edit/MU4aoFI34ZGjjtQ5wS9j?p=preview) you can see in the console, 3 separate subscribes are sharing the same observable sequence (http request).

Here is another example goes one step further and stores the result in the service (https://plnkr.co/edit/M9ZIViYhSbKzPlzKXC7H?p=preview). This acts as a cache, so if a component that is loaded later needs the data, an additional api call is not needed. But you do not need that functionality for this piece.

LLai
  • 13,128
  • 3
  • 41
  • 45
  • Thanks @LLai. Here, both Metadata(clientJson) are different. By using your approach one data is shared among all components. Is there any approach, by which, we can get different data for different components as we can see "viewbys" are different in clientJson(pie-chart.component.ts and line-chart.component.ts) . –  Jul 03 '17 at 18:54
  • In second example of yours, this.observableShare = Observable.of('API RESULT') // mimic api request. What is 'API RESULT'? Is that url? –  Jul 04 '17 at 06:04
  • @ManzerAhmad 'API RESULT' is just an example of what the data the api is returning. – LLai Jul 04 '17 at 15:03
  • @ManzerAhmad To do what you are asking, you need a single component to fire the api call. This component needs knowledge of all the different meta data. This is because once the API request is initiated it can not be added to. If possible I would recommend having a parent component of (line-chart & pie-chart) make the api call, then pass that data down to line-chart & pie-chart as needed. (This is assuming the metadata affects what you send to the api) – LLai Jul 04 '17 at 15:15
  • Can u do it in plunker Please, so that, i can understand it easily. –  Jul 04 '17 at 16:43
  • @LLai.How to do that? Can u give me a brief hint through code please? –  Jul 05 '17 at 07:07
  • @ManzerAhmad here is a simple example of what I am saying. https://plnkr.co/edit/uhuDM3bmdvmR0zUDSctn?p=preview so you make 1 api request at the parent level, then pass that data down to each child as needed. – LLai Jul 06 '17 at 13:18