Reputation: 357
autoRefreshGateways() {
return interval(GATEWAY_REFRESH_INTERVAL)
.pipe(
startWith(0),
takeUntil(this.stopAutoRefresh),
exhaustMap(() => this.fetchAllData())
).subscribe(
(gateways) => {
this.gateways = gateways;
},
() => {
this.notificationsService.error(this.translateService.instant('zerotrust.gateway.list.error'), '')
}
);
}
I have this autoRefresh function which calls the api every 5 sec. In some scenario i dont want to wait for 5 second. I want to call fetchAllData immediatly based on some action from the UI. I have written a different function for that which will call fetchAllData. However is there a better solution to this?
Upvotes: 1
Views: 646
Reputation: 3409
I think merge
is your friend here.
Try to break down the problem by thinking of what's the signal to trigger the update: In your case you have 2 sources: autoRefreshes and forceRefreshes. That's easy to represent:
const forceRefresh = new Subject(); // In your case, you'd have this defined as an instance property of your class, so it can be called from outside.
const autoRefreshes = interval(GATEWAY_REFRESH_INTERVAL)
.pipe(
startWith(0),
takeUntil(this.stopAutoRefresh)
);
Then you can join these two signals toghether with merge, and call the API you need:
merge(
forceRefresh,
autoRefreshes
).pipe(
exhaustMap(() => this.fetchAllData())
).subscribe(/* ... */)
Upvotes: 1
Reputation: 31125
You could send the delay as a parameter to the function and use RxJS timer()
as the source observable instead of interval()
.
Try the following
Controller
autoRefreshGateways(delay = 5000, interval = 5000) { // <-- default: trigger refresh after 5s and refresh every 5s
timer(delay, interval).pipe(
startWith(0),
takeUntil(this.stopAutoRefresh),
exhaustMap(() => this.fetchAllData())
).subscribe(
(gateways) => {
this.gateways = gateways;
},
() => {
this.notificationsService.error(this.translateService.instant('zerotrust.gateway.list.error'), '')
}
);
}
Now you could call the function accd. to your requirement.
From UI input
...
<!-- trigger auto refresh immediately and refresh every 5s -->
<button (mouseup)="autoRefreshGateways(0)">Auto refresh</button>
From some other functions in controller
someFunc() {
...
this.autoRefreshGateways(); // <-- trigger auto refresh after 5 seconds and refresh every 5s (default)
};
someOtherFunc() {
...
this.autoRefreshGateways(3000, 10000); // <-- trigger auto refresh after 3s and refresh every 10s
}
Upvotes: 0
Reputation: 2369
I would suggest the usage of a Subject
that would combine with the interval. If either the interval or the subject emits, you then trigger the thing.
forceTrigger$ = new Subject();
autoRefreshGateways() {
return combineLatest(
interval(GATEWAY_REFRESH_INTERVAL),
this.forceTrigger$.pipe(startWith(true))
)
.pipe(
startWith(0),
takeUntil(this.stopAutoRefresh),
exhaustMap(() => this.fetchAllData())
).subscribe(
(gateways) => {
this.gateways = gateways;
},
() => {
this.notificationsService.error(this.translateService.instant('zerotrust.gateway.list.error'), '')
}
);
}
// Example of forcing the trigger
onUIAction() {
this.forceTrigger$.next(true);
}
Upvotes: 0