3

I am using Ionic3 with a rxjs/Observable. I have the following function, and for some reason, even though the function is only called once, the 3rd line gets fired twice.

findChats(): Observable<any[]> {
    return Observable.create((observer) => {
        this.chatSubscription2 = this.firebaseDataService.findChats().subscribe(firebaseItems => {
            this.localDataService.findChats().then((localItems: any[]) => {
                let mergedItems: any[] = [];
                if (localItems && localItems != null && firebaseItems && firebaseItems != null) {
                    for (let i: number = 0; i < localItems.length; i++) {
                        if (localItems[i] === null) {
                            localItems.splice(i, 1);
                        }
                    }
                    mergedItems = this.arrayUnique(firebaseItems.concat(localItems), true);
                } else if (firebaseItems && firebaseItems != null) {
                    mergedItems = firebaseItems;
                } else if (localItems && localItems != null) {
                    mergedItems = localItems;
                }
                mergedItems.sort((a, b) => {
                    return parseFloat(a.negativtimestamp) - parseFloat(b.negativtimestamp);
                });
                observer.next(mergedItems);
                this.checkChats(firebaseItems, localItems);
            });
        });
    });
}

Problem

This is causing a problem because this.chatSubscription2 is taking the value of the second subscription, and the first subscription gets lost, not allowing me to ever unsubscribe.

line 2 is executed once
line 3 is executed twice

Question

How do I create an Observable with only one subscription?

Thanks

UPDATE

I change the code to the following using share(), but the 3rd line still gets executed twice:

findChats(): Observable<any[]> {
    return Observable.create((observer) => {
        const obs = this.firebaseDataService.findChats().share();
        this.chatSubscription2 = obs.subscribe(firebaseItems => {
                     ....
Richard
  • 8,193
  • 28
  • 107
  • 228
  • Make `const obs$ = findChats().share()` and then subscribe only to `obs$.subscribe(...)` – martin Jul 03 '17 at 12:03
  • Thanks Martin, but: `[ts] Property 'share' does not exist on type 'Observable'` – Richard Jul 03 '17 at 12:05
  • 1
    https://stackoverflow.com/questions/37073705/property-catch-does-not-exist-on-type-observableany – martin Jul 03 '17 at 12:28
  • Thanks, I can now use `shar(e)`, but it still doesn't work, I have probably implemented it incorrectly. Please see UPADTE above. – Richard Jul 03 '17 at 12:36
  • did you happened to calll `this.chatSubscription2.subscribe()` somewhere else? – CozyAzure Jul 03 '17 at 12:37
  • Hi CozyAzure, nope, It's only called once. the only time a use `chatSubscription2` is setting it up (as shown above), and `chatSubscription2.unsubscribe()` which is not called when I test this. – Richard Jul 03 '17 at 12:39

1 Answers1

4

As other users have suggested, while findChats is only called once, it would seem that the observable it returns is subscribed to multiple times. create returns a cold observable which will cause all the internal logic to be executed for each subscription. You can whack a share on the end of the whole thing (i.e. outside / after the create call) to test this, but I would suggest the solution would actually be simpler if you did not use create at all, and rather just mapped / flatMapped / switchMapped your original stream into your desired stream (to avoid manual subscription management).

Matt Burnell
  • 2,646
  • 1
  • 22
  • 23
  • Thank you, your are right. `share()` fixed my problem. but as you suggest, I will try refractor my code not to use `create`. – Richard Jul 03 '17 at 13:30