Reputation: 3718
I have the following code. It gets an array of Patients and builds a rows object this.rows
that I show in a table on the frontEnd of this angular 4 component (I am also using rxjs 5.5).
My issue is the hasAlert property of each row is assigned by a call to hasAlerts(). In the HasAlerts method, I make an http request, for each patient via this.dataService.fetchItems<Observation>(
.
When there are many patients, too many HTTP requests will occur asynchronously and they will start to fail (timeout) from HasAlerts(). Is there a way to throttle this,or process one Observable at a time from hasAlerts()?
Below are possible ways to solve this
Code is below
ngOnInit(): void {
this.store.dispatch(new patients.Load([]));
this.patients$ = this.store.select(fromPatients.getAll);
var patientsAlertsProcessed =0;
this.patients$.debounceTime(2000).map(p =>{//Emits Observable<Patient[]>s, the debounceTime is to take the last one as it builds up
this.rows = p.map(pat => {// p = Patient[], iterate through the array of patients
var observations=0;
var rowX= {
username: pat.username,
id: pat.id,
hasAlert:false,
};
if (patientsAlertsProcessed<15){// this is done to throttle the HasAlerts Method
this.hasAlerts(pat).do(x => {
observations++;
if (observations>0)
{
rowX.hasAlert=true;
}
}).subscribe();
patientsAlertsProcessed++;
}
return rowX;
});
}).subscribe(
()=> { },
()=> {
this.table.recalculatePages();
}
);
}
hasAlerts(pat: Patient): Observable<Observation> {
var obs$= this.dataService.fetchItems<Observation>(// this is making an HTTP get request
"Observation",
null,
pat.id
).filter(function (x){
if (x.category.coding[0].code == "GlucoseEvent"){
return true;
}
else{
return false;
}
}
);
return obs$;
}
Upvotes: 1
Views: 540
Reputation: 17752
You may want to try something along these lines.
const concurrency = 10;
const rowsWithAlerts = [];
this.patients$.debounceTime(2000)
.switchMap(patients => Observable.from(patients)) // patients is of type Patient[]
.mergeMap(patient => {
rowsWithAlerts.push(patient);
this.hasAlerts(patient).do(
hasAlertsResult => {
// here you have hold to both the patient and the result of
// hasAlerts call
patient.hasAlerts = hasAlertsResult;
}}), concurrency)
.subscribe(
() => this.rows = rowsWithAlerts;
)
The key here is to use the mergeMap
operator with the concurrency level set to a value, in this example 10 but clearly can be anything.
This allows to limit the number of observables to which you subscribe at the same time, which in your case means to limit the number of http calls you make.
Upvotes: 2