Skip to content

Commit 68e83fa

Browse files
committed
order listener invocation
1 parent de1ec0c commit 68e83fa

1 file changed

Lines changed: 35 additions & 2 deletions

File tree

core/src/refx/subs.cljc

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

79+
(defonce ^:private listeners-state
80+
(atom {:counter 0 :pending '()}))
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). This will ensure that there's only
86+
a single render per db update."
87+
[listener-key listener-fn]
88+
(swap! listeners-state (fn [state]
89+
(cond-> (update state :counter inc)
90+
(not (signal? listener-key))
91+
(update :pending conj [listener-key listener-fn]))))
92+
93+
(when (signal? listener-key)
94+
(listener-fn))
95+
96+
(interop/next-tick
97+
(fn []
98+
(let [listener-fns (atom '())]
99+
(swap! listeners-state (fn [state]
100+
(let [{:keys [counter pending] :as new-state}
101+
(update state :counter dec)]
102+
(if (zero? counter)
103+
(do
104+
(reset! listener-fns pending)
105+
(assoc new-state :pending '()))
106+
new-state))))
107+
108+
;; ensure listeners are triggered in the order they are registered
109+
(doseq [[_ f] (sort-by first @listener-fns)]
110+
(f))))))
111+
79112
(deftype Listeners [^:mutable listeners]
80113
Object
81114
(empty? [_] (empty? listeners))
@@ -84,8 +117,8 @@
84117
(remove [_ k]
85118
(set! listeners (dissoc listeners k)))
86119
(notify [_]
87-
(doseq [[_ f] listeners]
88-
(f))))
120+
(doseq [[k f] listeners]
121+
(invoke-listener k f))))
89122

90123
(defn- make-listeners []
91124
(Listeners. nil))

0 commit comments

Comments
 (0)