Skip to content

Instantly share code, notes, and snippets.

@trmcnvn
Last active December 23, 2021 21:59
Show Gist options
  • Save trmcnvn/b70dc2bc32455403a3b22a1bea2f4609 to your computer and use it in GitHub Desktop.
Save trmcnvn/b70dc2bc32455403a3b22a1bea2f4609 to your computer and use it in GitHub Desktop.
Reuse IntersectionObserver's
export function sortObject(object) {
Object.keys(object).reduce((prev, curr) => {
if (object[curr] !== null && typeof object[curr] === 'object') {
prev[curr] = sortObject(object[curr]);
return prev;
}
prev[curr] = object[curr];
return prev;
}, {});
}
import { sortObject } from './object';
const ObserverMap = new Map();
const ListenerMap = new WeakMap();
function mapGetWithDefault(map, key, value) {
let result = null;
if ((result = map.get(key))) {
return result;
}
map.set(key, value);
return value;
}
/**
* Returns an existing IntersectionObserver for the matching options,
* or creates a new one.
*
* @param options IntersectionObserver options
*/
export default function observerManager(options = {}) {
// Get an observer that we have already registered with these options,
// or create a new one.
const key = JSON.stringify(sortObject(options));
let observer = ObserverMap.get(key);
if (observer === undefined) {
const callback = entries => {
entries.forEach(entry => {
const targets = mapGetWithDefault(ListenerMap, entry.target, []);
targets.forEach(listener => listener(entry));
});
};
observer = new IntersectionObserver(callback, options);
ObserverMap.set(key, observer);
}
// Observe the target using the correct IntersectionObserver
return function observe(target, listener) {
const targets = mapGetWithDefault(ListenerMap, target, []);
targets.push(listener);
observer.observe(target);
// Return a function to cleanup
return function disconnect() {
const idx = targets.indexOf(listener);
targets.splice(idx, 1);
if (targets.length === 0) {
ListenerMap.delete(target);
return observer.unobserve && observer.unobserve(target);
}
};
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment