Utilizing the requestAnimationFrame
method implies that this process can be asynchronous, but with a sense of high priority?
If you integrate rxjs into your project and import the necessary rxjs components, you could implement something similar to the code snippet below...
const FRAMES_PER_SECOND = 15;
const initialConstraints = [1,2,3,4, 100000];
const others$: BehaviorSubject<number[]> = new BehaviorSubject();
// Subscribed to, emits combined
// constraints once per time
// others$.next(numArray) is called.
const constraints$ = others$.pipe(
map(
others => !others || !others.length ? initialConstraints
: [...initialConstraints, ...others]
)
);
// Subscribed to, emits a MouseEvent
// every time the mouse is moved
const moves$ = fromEvent(
document,
'mousemove'
);
type StepArgument = [MouseEvent, number[]];
// Subscribed, emits a two-element
// array each time others$.next is
// called or the mouse is moved, with
// actions executed as part of the
// animation scheduler.
const both$: Observable<StepArgument> = scheduled(
moves$.pipe(
debounceTime(1000 / FRAMES_PER_SECOND),
combineLatestWith(constraints$)
),
animationFrameScheduler
);
// Upon invocation, `both$` will emit values
// into the step argument until the subscribed
// object's `unsubscribe` function is invoked.
function watchMouse(step: ((arg: StepArgument) => void) {
return both$.subscribe(step);
}
In this context, the merging of two arrays takes place whenever the state of others$
changes. The code structure aims for readability.
This approach also provides room for future adaptability. If each variable constraint is represented by its own observable, an alternative implementation could be instead:
function getOtherObservables(): Observable<number | number[]>[] {?? whatever ??}
const constraints$: Observable<number[]> = of(initialConstraints).pipe(
combineLatest(...getOtherObservables()),
map(a => a.flat()),
shareReplay(1)
);
It might be more efficient not to generate a new two-element array per mouse event, however, this method prioritizes readability and flexibility while maintaining performance by limiting updates to a maximum of 15 frames/second and only performing operations when necessary.
Note: When subscribing to both$
, it may not emit any values until the mouse moves since it starts monitoring the mouse event stream without recollection of prior movements. Solutions to address this issue are available if required.
(Disclaimer: example code has not been debugged)