To better understand how rxjs/combineLatest
works, I'm going to create a simple window resize observer function.
Some requirements:
The function should accept a callback
that will be called whenever the window is resized.
function createWindowResizeObserver(callback) {
...
}
The callback
function will takes an object with dimensions:
function resizeCallback(dimensions) {
const { width, height } = dimensions;
console.log({ width, height });
}
Finally, createWindowResizeObserver
must return an unsubscribe
function to unsubscribe from these events later, if necessary.
const unsubscribe = createWindowResizeObserver(resizeCallback);
// unsubscribe later if necessary
unsubscribe();
Let's implement this!
First, create a stream of window width and height changes
import { fromEvent } from "rxjs";
import { map } from "rxjs/operators";
// Create a stream from `window` resize events
// and map it to get width of window
const width = fromEvent(window, "resize").pipe(
map(() => window.innerWidth)
);
// Do the same with height
const height = fromEvent(window, "resize").pipe(
map(() => window.innerHeight)
);
Then create a dimensions stream.
To do that I need to combine
each change of width with latest
value of height and vice versa :)
And then map result to the required shape
// add combineLatest to imports
import { fromEvent, combineLatest } from "rxjs";
// combine here
const combined = combineLatest(width, height);
// `combined` produces an array of width and height values
const dimensions = combined.pipe(
map(([width, height]) => ({ width, height }))
);
It will be good to add little throttling to prevent high cpu utilization
import { map, throttleTime } from "rxjs/operators";
const dimensions = combined.pipe(
throttleTime(100),
map(([width, height]) => ({ width, height }))
);
To subscribe on dimensions stream use subscribe
method
// subscribe method returns the unsubscribe function
const unsubscribe = dimensions.subscribe(callback);
Finally wrap up all stuff to single function:
import { fromEvent, combineLatest } from "rxjs";
import { map, throttleTime } from "rxjs/operators";
function createWindowResizeObserver(callback) {
const width = fromEvent(window, "resize").pipe(
map(() => window.innerWidth)
);
const height = fromEvent(window, "resize").pipe(
map(() => window.innerHeight)
);
const combined = combineLatest(width, height);
const dimensions = combined.pipe(
throttleTime(100),
map(([width, height]) => ({ width, height }))
);
const unsubscribe = dimensions.subscribe(callback);
return unsubscribe;
}
And that's all!
Let's check the result
Open the Console and change preview window with or height
Top comments (0)