I need a Signal-based utility to keep track of the status of multiple async operations performed with observables (e.g. HTTP calls). So I can use those signals also in Components using the OnPush change detection strategy.
Suppose I have an AnimalService that you use to fetch animals:
@Injectable({
providedIn: 'root',
})
export class AnimalService {
private readonly httpClient = inject(HttpClient);
fetchCats() {
return this.httpClient.get('animals.org/cats');
}
fetchDogs() {
return this.httpClient.get('animals.org/dogs');
}
fetchChickens() {
return this.httpClient.get('animals.org/chickens')
}
}
I want to have a centralised place that keeps track of when some animals are being loaded.
Also, I want to track this from places that might not even be aware of where the actual calls are performed.
For example, suppose Component A triggers the fetch calls, but Component B wants actually to know whether or not there are animals being loaded to display a spinner.
I solved this issue by creating a generic
LoadingStatusManagerutility that looks like this:To use it, first of all, you define a type that defines one key (string) per each call that you want to track:
Then you create a new
LoadingStatusManagerobject using this type:Now use the
loadingStatusManagerobject to watch your async operations:Now you can easily get a
Signalthat watches if any of the async operations are in progress:This is because we did not pass any key to
getSignalWatchingOnProps, so by default it watches on all keys.If we want to get a Signal that is watching only on a specific set of keys, we can use:
The complete code of the
AnimalServiceis:From outside, any Component or Service can inject the
AnimalServiceand get the signals:This can be used also in the template of a Component using
OnPushchange detection strategy. Thanks to the Angular Signals, the template will be refreshed automatically each time the value of the signals change.