1
votes

I am receiving data from firebase through RxJS via the query below:

getAppliedLocalTags() {
    this.tagSub = this.pageService
      .getTagsOnPage(this.workspaceId, this.currentPage.id)
      .pipe(
        switchMap((references) => from(references)),
        mergeMap((ref) => this.afs.doc(ref).snapshotChanges()),
        map((actions) => actions.payload.data()),
        scan((allTagData, tagData) => [...allTagData, tagData], [])
      )
      .subscribe((data) => {
        this.appliedTags = data;
      });
    // STOP THE SUB ONCE WE GET THE TAGS
    setTimeout(() => {
      console.log("un-subbed from tags");
      this.tagSub.unsubscribe();
    }, 2000);
  }

When the subscription comes in, this.appliedTags gets populated with all of the 'tags' coming from the database.

In this case, I only want the values once. After I get all values, I unsubscribe, but the best method that I have at the moment for doing this is by using setTimeout(() => {}, 2000), which is not ideal as the time will vary based on network, number of tags, etc..

Unfortunately, I have yet to find a solution that unsubscribes from the data stream after an observable has 'completed.'

Is there a way to unsubscribe after the observable 'completes,' or stops emitting values?

Thank you!!

1
When observable is complete - all subs are gone. - Antoniossss
take(10) will unsubscribe after 10 emissions - ggradnig
Sorry, I forgot to remove take(10), as the number of tags will vary. - Mason Secky-Koebel

1 Answers

1
votes

This can be solve in two ways :

Promise way:

getAppliedLocalTags() {
    this.tagSub = this.pageService
      .getTagsOnPage(this.workspaceId, this.currentPage.id)
    .pipe(
        switchMap((references) => from(references)),
        mergeMap((ref) => this.afs.doc(ref).snapshotChanges()),
        map((actions) => actions.payload.data()),
        scan((allTagData, tagData) => [...allTagData, tagData], [])
      )
    .toPromise().then((data) => {
            this.appliedTags = data;
        }).catch(err => {
        // handle error
    });
}

Another way is use take operator:

getAppliedLocalTags() {
    this.tagSub = this.pageService
      .getTagsOnPage(this.workspaceId, this.currentPage.id)
      .pipe(
        switchMap((references) => from(references)),
        mergeMap((ref) => this.afs.doc(ref).snapshotChanges()),
        map((actions) => actions.payload.data()),
        scan((allTagData, tagData) => [...allTagData, tagData], []),
        take(1) // This will emit only once then..
      )
      .subscribe((data) => {
        this.appliedTags = data;
      });
  }