4

Problem Statement: Currently I have a frontend application which has 5 graphs In a page (Each Graph have a different endpoint to fetch the data) to be rendered based on the data retrieved from the database, and I have a dropdown which updates the charts based on the value selected from the drop-down.

Now In the frontend the graphs will be loaded with default values and My requirement is that whenever users select any dropdown and if any HTTP calls(from the default values) running I want to cancel them and make new request(The main reason because sometimes the data from the previous request takes longer than latest data which is selected from the drop-down hence my graphs are still updated with old request instead of new value selected from the dropdown as I could see from the Chrome Network Tab ,Old Request gets finished after the latest request hence graph updates with old request) and all these graphs makes parallel request to these methods to render the data.

With help of @Amit Chigadani currently I have the below function written in service but with this approach, the endpoints from even the latest request getting canceled and graphs are not rendered at all, can you please help me with the approach

In the Service

getData(url: string) {
    const finalRequest = new RequestModel(this.myModel);
    const body = JSON.stringify(finalRequest);
    const headers = new Headers({ "Content-Type": "application/json" });
    const options = new RequestOptions({ headers: headers });

    return this.http.post(url, body, options).switchMap((res) => {
        const resp = res.json();
        return Observable.of(resp);
    });
}

In the Component

public mySub: Subscription;

if (this.mySub !== undefined) {

    this.mySub.unsubscribe();
}

this.mySub = this.myService.getData(this.url).subscribe((data) => {
    try {
    }
    catch (err) {//do something if error
    }
    return this.mySub;
});

Versions

  • Angular : 4.0.1
  • rxjs : 5.0.3
Mahesh G
  • 1,226
  • 4
  • 30
  • 57
  • The component code that you show here, is it for parent component that contains all those 5 child components? I am making a new answer, if that is true – Amit Chigadani Sep 04 '18 at 12:39
  • Why you unsubscribe from mySub ? SwitchMap should cancel previous ones and take latest http request already. – Okan Aslankan Sep 04 '18 at 12:49

1 Answers1

2

Ok, forget switchMap, that is of no use here.

From chat :

I understood the problem Is mainly because since I have different child components which parallelly making a call this method and I have same Subscription for all the Graphs hence any time new request comes its unsubscribing the requests.. Is there any way to resolve this one out

I see that you are calling the same method for each http requests. My guess is that you are doing this in your parent component whenever one of the child emits dropdown valueChange event.

EDIT :

From chat It was made clear that, OP actually meant parent-child components in terms of inheritance and not angular context.

i.e Child1, Child2... classes are extending from Parent

So each of these Child components will now have a separate instance of mySub Subscription object which can be subscribed parallely. And unsubscribing from the previous request from one of the child component should not unsubscribe instances from other child components.

Only if the same component say Child1 fires a second http requests, then its own previous subscription will be killed and newer subscription is created on child1 instance.

See this demo to check that instances are not shared across the child components. They are all independent.

Amit Chigadani
  • 28,482
  • 13
  • 80
  • 98
  • Note : I assume OP is using `angular2`. Accordingly i have added this answer. – Amit Chigadani Sep 01 '18 at 19:54
  • Hi Amit thanks for the answer specifically I am using Angular 4 but when I use the switchMap I am getting an error that `You provided an invalid object where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.` – Mahesh G Sep 02 '18 at 03:49
  • If you want to perform any logic in service, then you can still do it inside `switchMap` only. In that case you can create a block and then `return` from `switchMap`. Check the updated answer. – Amit Chigadani Sep 02 '18 at 04:42
  • Thanks Amit , But still I am facing the same issue when calling this is a method on my component and over on the data type it shows empty object instead of data:any [image1](https://ibb.co/bSassz) [image2](https://ibb.co/hH3dXz) – Mahesh G Sep 02 '18 at 05:05
  • It isn't showing empty object. Error says that you cannot get property `filter` from that object. Because it does not know the type of that object. You may declare its type as `any`. `subscribe((data : any) => ...` And also what does `console.log(data)` prints inside component. Do you get the response? – Amit Chigadani Sep 02 '18 at 05:08
  • No, I tried to console the data but still, I am getting the same error like below `core.es5.js:1084 ERROR TypeError: You provided an invalid object where a stream was expected. You can provide an Observable, Promise, Array, or Iterable. at Object.subscribeToResult (subscribeToResult.js:73) at SwitchMapSubscriber._innerSub (switchMap.js:101) at SwitchMapSubscriber._next (switchMap.js:94) at SwitchMapSubscriber.Subscriber.next (Subscriber.js:89) at XMLHttpRequest.onLoad (http.es5.js:1205) at ZoneDelegate.invokeTask (zone.js:398)` – Mahesh G Sep 02 '18 at 05:16
  • What is your rxjs version? probably you need pipe then. – Amit Chigadani Sep 02 '18 at 05:16
  • I am using `"rxjs": "5.0.3",` – Mahesh G Sep 02 '18 at 05:17
  • @AmitChigadani: please mention that we don't need to provide them again.. your chat discussion is misleading.. – Ashish Ranjan Sep 04 '18 at 14:07