Skip to content

Instantly share code, notes, and snippets.

@OhadC
Last active October 1, 2019 11:04
Show Gist options
  • Select an option

  • Save OhadC/9026001669ed51e886cdf7bdfd85674e to your computer and use it in GitHub Desktop.

Select an option

Save OhadC/9026001669ed51e886cdf7bdfd85674e to your computer and use it in GitHub Desktop.
import { Observable } from "rxjs";
// code based on https://rxjs-dev.firebaseapp.com/guide/v6/pipeable-operators
// Usages:
// uniqueEventCounter(250, buttonComperator, 2) => for click/double-click, when more than 1 button emit events.
// uniqueEventCounter(250, trueComperator, 2) => for click/double-click, when only 1 button emit events.
export const trueComperator = (a: any, b: any) => true;
export const simpleComperator = (a: any, b: any) => a === b;
export const buttonComperator = (a: MouseEvent, b: MouseEvent) => a.srcElement === b.srcElement;
export const uniqueEventCounter = <T>(interval: number, comperator: Comperator<T> = simpleComperator, maxTimes?: number) => (
source: Observable<T>
) =>
new Observable<DispatchedValue<T>>(observer => {
let prevTimeout: any;
let prevValue: T;
let timesCounter = 0;
function onDestroy() {
clearPrevTimeout();
}
function dispatch(value: T, times: number) {
observer.next({ value, times });
resetCache();
}
function clearPrevTimeout() {
if (prevTimeout) {
clearTimeout(prevTimeout);
prevTimeout = undefined;
}
}
function ceateNewTimeout() {
clearPrevTimeout();
prevTimeout = setTimeout(() => {
dispatch(prevValue, timesCounter);
}, interval);
}
function resetCache() {
clearPrevTimeout();
prevValue = undefined;
timesCounter = 0;
}
return source.subscribe({
next(value) {
if (prevValue && comperator(prevValue, value)) {
timesCounter++;
if (maxTimes === timesCounter) {
dispatch(prevValue, timesCounter);
} else {
ceateNewTimeout();
}
} else {
if (prevValue) {
dispatch(prevValue, timesCounter);
}
prevValue = value;
timesCounter = 1;
ceateNewTimeout();
}
},
error(err) {
onDestroy();
observer.error(err);
},
complete() {
onDestroy();
observer.complete();
}
});
});
type DispatchedValue<T> = { value: T; times: number };
type Comperator<T> = (a: T, b: T) => boolean;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment