amis-rpc-design/node_modules/react-redux/es/utils/Subscription.js
2023-10-07 19:42:30 +08:00

127 lines
2.6 KiB
JavaScript

import { getBatch } from './batch'; // encapsulates the subscription logic for connecting a component to the redux store, as
// well as nesting subscriptions of descendant components, so that we can ensure the
// ancestor components re-render before descendants
function createListenerCollection() {
const batch = getBatch();
let first = null;
let last = null;
return {
clear() {
first = null;
last = null;
},
notify() {
batch(() => {
let listener = first;
while (listener) {
listener.callback();
listener = listener.next;
}
});
},
get() {
let listeners = [];
let listener = first;
while (listener) {
listeners.push(listener);
listener = listener.next;
}
return listeners;
},
subscribe(callback) {
let isSubscribed = true;
let listener = last = {
callback,
next: null,
prev: last
};
if (listener.prev) {
listener.prev.next = listener;
} else {
first = listener;
}
return function unsubscribe() {
if (!isSubscribed || first === null) return;
isSubscribed = false;
if (listener.next) {
listener.next.prev = listener.prev;
} else {
last = listener.prev;
}
if (listener.prev) {
listener.prev.next = listener.next;
} else {
first = listener.next;
}
};
}
};
}
const nullListeners = {
notify() {},
get: () => []
};
export function createSubscription(store, parentSub) {
let unsubscribe;
let listeners = nullListeners;
function addNestedSub(listener) {
trySubscribe();
return listeners.subscribe(listener);
}
function notifyNestedSubs() {
listeners.notify();
}
function handleChangeWrapper() {
if (subscription.onStateChange) {
subscription.onStateChange();
}
}
function isSubscribed() {
return Boolean(unsubscribe);
}
function trySubscribe() {
if (!unsubscribe) {
unsubscribe = parentSub ? parentSub.addNestedSub(handleChangeWrapper) : store.subscribe(handleChangeWrapper);
listeners = createListenerCollection();
}
}
function tryUnsubscribe() {
if (unsubscribe) {
unsubscribe();
unsubscribe = undefined;
listeners.clear();
listeners = nullListeners;
}
}
const subscription = {
addNestedSub,
notifyNestedSubs,
handleChangeWrapper,
isSubscribed,
trySubscribe,
tryUnsubscribe,
getListeners: () => listeners
};
return subscription;
}