debounceTime only after first value
Here's my 2 cents / an answer I modified from another post with java-ngrx.
dbounce-time-after.ts
import { OperatorFunction, SchedulerLike, concat } from "rxjs";
import { async } from "rxjs/internal/scheduler/async";
import { debounceTime, publish, take } from "rxjs/operators";
export function debounceTimeAfter(
amount: number,
dueTime: number,
scheduler: SchedulerLike = async,
): OperatorFunction<number, number> {
return publish(value =>
concat(
value.pipe(take(amount)),
value.pipe(debounceTime(dueTime, scheduler))),
)
);
}
export function debounceTimeAfterFirst(
dueTime: number,
scheduler: SchedulerLike = async,
): OperatorFunction<number, number> {
return debounceTimeAfter(1, dueTime, scheduler);
}
example.ts
of(1, 2, 3, 4, 5)
.pipe(
tap(value => console.log("TAP", value)),
debounceTimeAfterFirst(50)
)
.subscribe(value => console.log(value));
console
TAP 1
1
TAP 2
TAP 3
TAP 4
TAP 5
5
But you could also start debouncing after n
number of emits with debounceTimeAfter
.
It's more flexible to use debounce instead of debounceTime.
searchQueries.pipe(debounceTime(1000))
is equal to:
searchQueries.pipe(debounce(() => timer(1000))
You can create your own heuristic to determine what timeout needs to be used. For example:
searchQueries.pipe(debounce(() => timer(getTimeout()))
...
const getTimeout = () => {
return iterations === 1 ? 0 : 1000;
};
In that scenario you need to track the iterations count on your own and increase it with each value but there are many ways to do it without messing a lot with the code. I simply created a wrapped observable object that contains the original observable and the counting logic. Something like this:
export default class ObservableWrapper {
...
next(parameters) {
this.iterations++;
this.observable.next(parameters);
}
}
You could use multicast
or maybe even throttleTime
:
searchQueries.pipe(
multicast(new Subject(), s => merge(
s.pipe(take(1)),
s.pipe(skip(1), debounceTime(1000)),
)),
);
Since RxJS 6 the throttleTime
operator accepts a config parameter where you can tell it to emit both leading and trailing emissions. Maybe this will do what you want instead of debounceTime
.
searchQueries.pipe(
throttleTime(1000, undefined, { leading: true, trailing: true }),
);