Subscription.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. import { getBatch } from './batch'; // encapsulates the subscription logic for connecting a component to the redux store, as
  2. // well as nesting subscriptions of descendant components, so that we can ensure the
  3. // ancestor components re-render before descendants
  4. var nullListeners = {
  5. notify: function notify() {}
  6. };
  7. function createListenerCollection() {
  8. var batch = getBatch();
  9. var first = null;
  10. var last = null;
  11. return {
  12. clear: function clear() {
  13. first = null;
  14. last = null;
  15. },
  16. notify: function notify() {
  17. batch(function () {
  18. var listener = first;
  19. while (listener) {
  20. listener.callback();
  21. listener = listener.next;
  22. }
  23. });
  24. },
  25. get: function get() {
  26. var listeners = [];
  27. var listener = first;
  28. while (listener) {
  29. listeners.push(listener);
  30. listener = listener.next;
  31. }
  32. return listeners;
  33. },
  34. subscribe: function subscribe(callback) {
  35. var isSubscribed = true;
  36. var listener = last = {
  37. callback: callback,
  38. next: null,
  39. prev: last
  40. };
  41. if (listener.prev) {
  42. listener.prev.next = listener;
  43. } else {
  44. first = listener;
  45. }
  46. return function unsubscribe() {
  47. if (!isSubscribed || first === null) return;
  48. isSubscribed = false;
  49. if (listener.next) {
  50. listener.next.prev = listener.prev;
  51. } else {
  52. last = listener.prev;
  53. }
  54. if (listener.prev) {
  55. listener.prev.next = listener.next;
  56. } else {
  57. first = listener.next;
  58. }
  59. };
  60. }
  61. };
  62. }
  63. var Subscription =
  64. /*#__PURE__*/
  65. function () {
  66. function Subscription(store, parentSub) {
  67. this.store = store;
  68. this.parentSub = parentSub;
  69. this.unsubscribe = null;
  70. this.listeners = nullListeners;
  71. this.handleChangeWrapper = this.handleChangeWrapper.bind(this);
  72. }
  73. var _proto = Subscription.prototype;
  74. _proto.addNestedSub = function addNestedSub(listener) {
  75. this.trySubscribe();
  76. return this.listeners.subscribe(listener);
  77. };
  78. _proto.notifyNestedSubs = function notifyNestedSubs() {
  79. this.listeners.notify();
  80. };
  81. _proto.handleChangeWrapper = function handleChangeWrapper() {
  82. if (this.onStateChange) {
  83. this.onStateChange();
  84. }
  85. };
  86. _proto.isSubscribed = function isSubscribed() {
  87. return Boolean(this.unsubscribe);
  88. };
  89. _proto.trySubscribe = function trySubscribe() {
  90. if (!this.unsubscribe) {
  91. this.unsubscribe = this.parentSub ? this.parentSub.addNestedSub(this.handleChangeWrapper) : this.store.subscribe(this.handleChangeWrapper);
  92. this.listeners = createListenerCollection();
  93. }
  94. };
  95. _proto.tryUnsubscribe = function tryUnsubscribe() {
  96. if (this.unsubscribe) {
  97. this.unsubscribe();
  98. this.unsubscribe = null;
  99. this.listeners.clear();
  100. this.listeners = nullListeners;
  101. }
  102. };
  103. return Subscription;
  104. }();
  105. export { Subscription as default };