DEV Community

Cover image for Window resize observer based on RxJS combineLatest operator
dqunbp
dqunbp

Posted on • Edited on

2 3

Window resize observer based on RxJS combineLatest operator

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) {
  ...
}
Enter fullscreen mode Exit fullscreen mode

The callback function will takes an object with dimensions:

function resizeCallback(dimensions) {
  const { width, height } = dimensions;
  console.log({ width, height });
}
Enter fullscreen mode Exit fullscreen mode

Finally, createWindowResizeObserver must return an unsubscribe function to unsubscribe from these events later, if necessary.

const unsubscribe = createWindowResizeObserver(resizeCallback);

// unsubscribe later if necessary 
unsubscribe();
Enter fullscreen mode Exit fullscreen mode

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)
);
Enter fullscreen mode Exit fullscreen mode

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 }))
);
Enter fullscreen mode Exit fullscreen mode

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 }))
);
Enter fullscreen mode Exit fullscreen mode

To subscribe on dimensions stream use subscribe method

// subscribe method returns the unsubscribe function
const unsubscribe = dimensions.subscribe(callback);
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

And that's all!
Let's check the result

Open the Console and change preview window with or height

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

Top comments (0)

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more