I am using ngrx 6 with angular 6
In my ngrx store devtools I see that one of my actions is firing more often than I want. It's not breaking the app, its just cluttering the devtools output.
I am dispatching the action with:
this.store.dispatch(new RecentSearchesRequestedAction())
How can I best debounce / throttle this so that it does not dispatch more than once per second for example? Does ngrx have a built in solution? I know I could spend time working out why the action is firing so often but I don't really have time for that. What's best practice to achieve this? Thanks
The best solution would be to debounce whatever is calling this.store.dispatch, which would be outside ngrx.
You can throttle the output side of ngrx, for example:
this.store.select((x) => x.property)
.pipe(
debounceTime(1000)
).subscribe((v) => console.log(v));
... would log the value of x.property at most once per second. But to stop the inputs, you need to throttle before the calls are made to dispatch.
This is a complementary answer to the accepted one and dives into more details about where to actually place the debounce.
When working with FormControls it is simple to debounce because of valueChanges (example):
this.searchField.valueChanges
.debounceTime(400)
.switchMap(term => this.searchService.search(term))
.subscribe((result) => {
this.result = result.items
});
This relies on switchMap function which cancels existing calls and keeps the latest one.
When working with custom controls, cancellation typically requires custom code (example for a Kendo control which does not emit changes, but relies on events):
import { Directive, Input, HostListener, OnDestroy, Output, EventEmitter } from '@angular/core';
import { Subject, Subscription } from 'rxjs';
import { debounceTime } from 'rxjs/operators';
@Directive({
selector: '[afterValueChanged]'
})
export class AfterValueChangedDirective implements OnDestroy {
@Output()
public afterValueChanged: EventEmitter<any> = new EventEmitter<any>();
@Input()
public valueChangeDelay = 300;
private stream: Subject<any> = new Subject<any>();
private subscription: Subscription;
constructor() {
this.subscription = this.stream
.pipe(debounceTime(this.valueChangeDelay))
.subscribe((value: any) => this.afterValueChanged.next(value));
}
ngOnDestroy(): void {
this.subscription.unsubscribe();
}
@HostListener('valueChange', [ '$event' ])
public onValueChange(value: any): void {
this.stream.next(value);
}
}
<kendo-numerictextbox
(afterValueChanged)="onAfterValueChange($event)"
(valueChange)="onValueChange($event)">
</kendo-numerictextbox>
public onAfterValueChange(value: number): void {
this.value = value;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With