You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
126 lines
2.8 KiB
126 lines
2.8 KiB
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() { |
|
var batch = getBatch(); |
|
var first = null; |
|
var last = null; |
|
return { |
|
clear: function clear() { |
|
first = null; |
|
last = null; |
|
}, |
|
notify: function notify() { |
|
batch(function () { |
|
var listener = first; |
|
|
|
while (listener) { |
|
listener.callback(); |
|
listener = listener.next; |
|
} |
|
}); |
|
}, |
|
get: function get() { |
|
var listeners = []; |
|
var listener = first; |
|
|
|
while (listener) { |
|
listeners.push(listener); |
|
listener = listener.next; |
|
} |
|
|
|
return listeners; |
|
}, |
|
subscribe: function subscribe(callback) { |
|
var isSubscribed = true; |
|
var listener = last = { |
|
callback: 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; |
|
} |
|
}; |
|
} |
|
}; |
|
} |
|
|
|
var nullListeners = { |
|
notify: function notify() {}, |
|
get: function get() { |
|
return []; |
|
} |
|
}; |
|
export function createSubscription(store, parentSub) { |
|
var unsubscribe; |
|
var 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; |
|
} |
|
} |
|
|
|
var subscription = { |
|
addNestedSub: addNestedSub, |
|
notifyNestedSubs: notifyNestedSubs, |
|
handleChangeWrapper: handleChangeWrapper, |
|
isSubscribed: isSubscribed, |
|
trySubscribe: trySubscribe, |
|
tryUnsubscribe: tryUnsubscribe, |
|
getListeners: function getListeners() { |
|
return listeners; |
|
} |
|
}; |
|
return subscription; |
|
} |