@snipsonian/observable-state
Version:
Observable-state snippets (redux-like)
50 lines (49 loc) • 2.43 kB
JavaScript
import isArray from '@snipsonian/core/es/is/isArray';
import extendNotificationsToTrigger from './extendNotificationsToTrigger';
export default function createStateObserverManager() {
let observerCounter = 0;
const observerMap = {};
return {
registerObserver: ({ observerName, notificationsToObserve, onNotify, }) => {
observerCounter += 1;
const observer = {
id: observerCounter,
observerName,
notify: onNotify,
};
observerMap[observer.id] = Object.assign(Object.assign({}, observer), { notificationsToObserve });
return observer;
},
unRegisterObserver: (observer) => {
delete observerMap[observer.id];
},
notifyObserversOfStateChanges: ({ notificationsToTrigger, triggerParentNotifications, }) => {
if (isArray(notificationsToTrigger) && notificationsToTrigger.length > 0) {
const uniqueObserversToNotify = extendNotificationsToTrigger({
notificationsToTrigger,
triggerParentNotifications,
})
.reduce((accumulator, notificationToTrigger) => {
const matchingObservers = Object.values(observerMap)
.filter((registeredObserver) => registeredObserver.notificationsToObserve.includes(notificationToTrigger));
matchingObservers.forEach((observer) => {
const alreadyFoundObserver = accumulator
.find((observerToNotify) => observerToNotify.id === observer.id);
if (alreadyFoundObserver) {
alreadyFoundObserver.notifications.push(notificationToTrigger);
}
else {
accumulator.push(Object.assign(Object.assign({}, observer), { notifications: [notificationToTrigger] }));
}
});
return accumulator;
}, []);
if (uniqueObserversToNotify && uniqueObserversToNotify.length > 0) {
uniqueObserversToNotify.forEach((observerToNotify) => {
observerToNotify.notify({ notifications: observerToNotify.notifications });
});
}
}
},
};
}