Alexander Tarasenko
Alexander Tarasenko

Reputation: 912

Double requests when subscribing to subject

I have one component(bootstrap modal), where I edit some info. Then I send it using service. It looks like this

this.service.updateCompanyById(companyInfo, this.company.id, this.logoImage)
        .subscribe(
          (data) => {
            this.bsModalRef.hide();
          },
          (err) => console.log(err)
        );

In my service

updateCompanyById(company, companyId, logoImage?: File) {
    ... some code
    return 

    this.http.post(`${this.domainName}api/companies/update/${companyId}`, formData)
          .do(
            (data) => {
              this.companyUpdated.next()
              this.notificationService.notify('Company updated successfully!');
            }
          );
      }

As you see I use Subject, so another component knows that company was updated. That component just contains list of all companies, which it gets using service. In this component I have

// list of companies    
this.companiesService.companyUpdated
        .subscribe(
          () => {
            this.getCompaniesFromServer();
          }
        )
    getCompaniesFromServer() {
        this.companiesService.getCompaniesInfo()
          .pipe(
            share()
          )
          .subscribe(
            (data) => {
              this.rows = data;
              console.log(data);
            }
          );
      }

The problem I have is that all requests getting duplicated.

For example: I edit user for the first time and get one response with list of all users in my list of companies component. Then after editing it second time, I get two responses and so on. I assume the problem is with Subject but I can't understand what exactly is wrong. Please help me if you can, thanks in advance

Can anybody explain why does it happen and what is the reason for such behavior? Possible solution proposed by @misha130 is to add .pipe(first()) Another possible soultion (though I am not sure in it) is to add .pipe(take(1))

Upvotes: 1

Views: 131

Answers (2)

Alexander Tarasenko
Alexander Tarasenko

Reputation: 912

So, I looked at this problem once more, and realized what was the problem and what the possible solution is. I am still not sure if I got it right though.

First of all, I had two subscriptions to one subject I had it in one function

onEditCompany(){
    this.companiesService.companyUpdated
        .subscribe(
          (data) => {
            console.log(data);
            this.getCompaniesFromServer();
          }
        );
}

And then in another function

onCreateCompany() {
      this.companiesService.companyUpdated
            .subscribe(
              (data) => {
                console.log(data);
                this.getCompaniesFromServer();
              }
            );
    }

As far as I got it this created two subscriptions in one place, that's why I had multiple requests instead of one. So as far as I realized, that I need only one instance of companyUpdated, and as far as it will be received either from update company in service or from add company in that service I assume that I need just to move my this.companiesService.companyUpdated to ngOnInit, so it will listen to changes for both add new company and update company cases. So, now it looks like this: Remove old code from both onEditCompany() and onCreateCompany() and write the following in ngOnInit:

this.companyUpdatedSubscription = this.companiesService.companyUpdated
        .switchMap(
          () => this.companiesService.getCompaniesInfo()
        )
        .subscribe(
          (data) => this.rows = data
        );

Upvotes: 1

misha130
misha130

Reputation: 5706

Either add first() before the subscribe to signify that its only going to take the value once or dispose of the subscription after receiving it.

The issue here is not that the subscription gets twice the data but that there are two subscriptions. Option A:

this.companiesService.companyUpdated
        first().subscribe(
          () => {
            this.getCompaniesFromServer();
          }
        )

Option B:

let companyUpdateSubscription: Subscription =  this.companiesService.companyUpdated
            first().subscribe(
              () => {
                this.getCompaniesFromServer();
                companyUpdateSubscription.unsubscribe();
              }
            )

On a note: If you choose option A I would still do unsubscribe onDestroy for the sake of memory management.

Upvotes: 1

Related Questions