Skip to content

Commit 5b06de5

Browse files
committed
group listener notifications
1 parent de1ec0c commit 5b06de5

1 file changed

Lines changed: 34 additions & 2 deletions

File tree

core/src/refx/subs.cljc

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,38 @@
7676
(doseq [[_ sub] @sub-cache]
7777
(dispose! sub)))
7878

79+
(defonce ^:private listeners-state
80+
(atom {:counter 0 :pending (sorted-map)}))
81+
82+
(defn- invoke-listener
83+
"This function is responsible for ensuring that signal listeners
84+
(from DynamicSubs) are called before triggering regular listeners
85+
(eg: added via use-sub hook). Listeners are triggered in the order they
86+
were registered. This function ensures that one db update will only trigger
87+
a single render."
88+
[listener-key listener-fn]
89+
(swap! listeners-state (fn [state]
90+
(cond-> (update state :counter inc)
91+
(not (signal? listener-key))
92+
(update :pending assoc listener-key listener-fn))))
93+
94+
(when (signal? listener-key)
95+
(listener-fn))
96+
97+
(interop/next-tick
98+
(fn []
99+
(let [listener-fns (atom {})]
100+
(swap! listeners-state (fn [state]
101+
(let [{:keys [counter pending] :as new-state}
102+
(update state :counter dec)]
103+
(if (zero? counter)
104+
(do
105+
(reset! listener-fns pending)
106+
(assoc new-state :pending (sorted-map)))
107+
new-state))))
108+
(doseq [[_ f] @listener-fns]
109+
(f))))))
110+
79111
(deftype Listeners [^:mutable listeners]
80112
Object
81113
(empty? [_] (empty? listeners))
@@ -84,8 +116,8 @@
84116
(remove [_ k]
85117
(set! listeners (dissoc listeners k)))
86118
(notify [_]
87-
(doseq [[_ f] listeners]
88-
(f))))
119+
(doseq [[k f] listeners]
120+
(invoke-listener k f))))
89121

90122
(defn- make-listeners []
91123
(Listeners. nil))

0 commit comments

Comments
 (0)