So I work on a Angular project in which many of the HTTP responses are used on multiple pages, so I wanted to cache the results on the front end so that they can be shared across the different components.
Here is a a "simple" example of my current implementation:
Service.ts
serviceData = new BehaviorSubject(false);
Component.ts
this.service.serviceData.pipe(takeUntil(this.unsubscribe$)).subscribe( response => {
if (!responseData) {
this.service.makeAPICall().subscribe(res => {
this.service.serviceData.next(res);
});
} else {
this.bankBranchDetails = bankData;
}
});
Using this snippet, I can share the same API results across multiple pages, and I can clear the cache by doing
this.service.serviceData.next(false)
In this simple example, things seemed fine (Still interested to know if there's a better way of doing this though).
The point where it becomes very complicated is when I need to use the result of one subscription as a parameter for 2 cached HTTP calls. For example, if I have a beneficiaryList and beneficiaryCategoryList which both depend on the currently selected profile, this is what I end up with.
this._paymentSaService.selectedProfile.pipe(switchMap(selectedProfile => {
this.selectedProfile = selectedProfile;
//Clear the beneficiaryCategoryList and beneficiaryListData because the profile just changed, meaning we need to fetch the new results
this._paymentSaService.beneficiaryCategoryList = new BehaviorSubject<BeneficiaryCategoryInterface[] | false>(false);
this._paymentSaService.beneficiaryListData = new BehaviorSubject<Beneficiary[] | false>(false);
return zip(this._paymentSaService.beneficiaryCategoryList, this._manageBeneficiary.beneficiaryList);
}), takeUntil(this.unsubscribe$)).subscribe(([categories, beneficiaries]) => {
if (!categories || !beneficiaries) {
this._paymentSaService.getBeneficiaryCategories(this.selectedProfile.ProfileId).subscribe(res => {
this._paymentSaService.beneficiaryCategoryList.next(res);
});
this._manageBeneficiary.getBeneficiariesList(this.selectedProfile.ProfileId).subscribe(res => {
this._manageBeneficiary.beneficiaryList.next(res);
});
} else {
//Both API calls completed, now we can handle the 2 pieces of data.
}
});
Is there a simpler way of doing this? This "solution" seems very overkill and confusing.
I would seriously appreciate any advice here to simplify my current way of doing things, because this project is turning out to be a bit of a birds nest.
EDIT: I have created a stackblitz with a replica of my implementation.
https://stackblitz.com/edit/angular-axpmm3?file=src/app/app.component.html
Oh, another downside of this implementation that I would love to fix, is that you have to clear the cache of both observables if you want to update even just 1 of them, due to me using a zip. But if I dont use a zip, the implementation would completely break because as soon as 1 API call finishes, it would kick off both calls again.