18

In my Angular2-typescript app, I'm using forkJoin to return an Observable only once all the parallel HTTP calls were made.

Issue: the subscription callback keeps being executed indefinitely

Here is my code:

http.service

import {Http} from "@angular/http";

constructor (private _http: HTTP) {}

makeGetRequest(....) {
    return this._http.get(URL)
           .map (res => res.json)
           .toPromise();

my.service

import {Observable} from "rxjs/Observable";
import {HttpService} from "http.service"

constructor (private _httpService: HttpService) {}

myMethod(): Observable<any[]> {
 return Observable.forkJoin(
            this._httpService.makeGetRequest(
                URL1
            ),
            this._httpService.makeGetRequest(
                URL2
            )
        )
}

my.component

import MyService from "my.service";
import Subscription from "rxjs";

constructor (private _service: MyService) {}

mySub: Subscription;

ngOnInit() {
    this.mySub = this._service.myMethod.subscribe(data => {
         data.forEach(console.log(data));
         this.mySub.unsubscribe();
     }
}

What I tried (same issue):

  • return an Observable in Http.service rather than a Promise
  • in my.component use .first().subscribe() instead of just subscribe()
  • put this.mySub.unsubscribe(); at the end of ngOnInit rather than inside the subscribe callback (also with setTimeout(() => ....))
Jaime Gómez
  • 6,961
  • 3
  • 40
  • 41
dragonmnl
  • 14,578
  • 33
  • 84
  • 129
  • 1
    What do you mean with 'the subscription callback keeps being executed indefinitely'? – Picci Nov 04 '16 at 18:48
  • 2
    The question doesn't make sense. forkJoin joins the results from *completed* observables and shouldn't be unsubscribed because it has a single value. If you have troubles with *being executed indefinitely*, please, provide an [MCVE](http://stackoverflow.com/help/mcve) that can replicate your issue – Estus Flask Nov 04 '16 at 18:50
  • 1
    @estus you're right. apparently this was happening because there subscription was instantiated twice and that caused the issue. Feel free to answer the question, I'll accept it ;) – dragonmnl Nov 04 '16 at 19:54
  • Sure. It's good that it was resolved easily. – Estus Flask Nov 04 '16 at 20:03

2 Answers2

54

As forkJoin reference says, it

Runs all observable sequences in parallel and collect their last elements.

This means that the operator gets values from completed observables and returns a completed observable with single value. There's no need to unsubscribe from it.

Estus Flask
  • 206,104
  • 70
  • 425
  • 565
  • What if we want two forkjoins? I'm having trouble because I call .forkjoin() multiple times in my app - I think rxjs doesnt like that :( – Kyle Vassella Jul 16 '19 at 19:51
  • What do you mean exactly? You can use multiple forkJoins. They just return observables that can be combined in any way. There shouldn't be any problems with that as long as your expectations from them are correct. If you have a specific case in mind, consider asking a new question that explains it and contains https://stackoverflow.com/help/mcve . – Estus Flask Jul 16 '19 at 20:31
  • In one component, I do a forkJoin to get certain results. I push some of those results into an array and then do a forkJoin with that array. But second forkJoin never returns data even though no error is ocurring. If I take out the initial forkJoin, then it works fine. Our forkjoin is actually an observable itself, and I think when I call it a second time, its still already set to the original values? – Kyle Vassella Jul 17 '19 at 01:21
  • After further testing, seems to be a timing issue. My second forkjoin runs as long as I put a setTimeout around it and stall it out at 3 seconds (haven't tried more/less time yet). This surprises me since due to my code I'd assume my first forkjoin completes before the second one fires.. – Kyle Vassella Jul 17 '19 at 01:36
2

You can cancel it. Let's say observables is an array of http requests you prepared to trigger (executed via httpClient).

this.forkJoinSubscription = forkJoin(observables).subscribe(responses => {
    . . . do something
});

this.forkJoinSubscription.unsubscribe();

You may notice in your network tab that those requests were cancelled.

Slaven Tomac
  • 1,552
  • 2
  • 26
  • 38
  • Do you know that this happens for a fact, or just hope it does that? – O'Rooney Feb 09 '23 at 01:40
  • Ok, so this answer is from 3.5 years ago :D, but if you notice in my answer "You may notice in your network tab that those requests were cancelled." so yeah, it happens (at least then it happened) – Slaven Tomac Feb 09 '23 at 08:08
  • OK, it was ambiguous meaning, thanks English :) "May" meaning it might happen. But you're saying it actually does happen - you saw it in the network tab. – O'Rooney Feb 09 '23 at 21:17