Last active
October 1, 2019 11:04
-
-
Save OhadC/9026001669ed51e886cdf7bdfd85674e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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