/
scheduling.cljc
60 lines (55 loc) · 2.58 KB
/
scheduling.cljc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
(ns com.fulcrologic.fulcro.algorithms.scheduling
"Algorithms for delaying some action by a particular amount of time."
(:require
[com.fulcrologic.guardrails.core :refer [>fdef =>]]
[clojure.core.async :as async]
[taoensso.timbre :as log]))
(defn defer
"Schedule f to run in `tm` ms."
[f tm]
#?(:cljs (js/setTimeout f tm)
:clj (let [active (atom true)
cancel (fn [] (reset! active false))]
(async/go
(async/<! (async/timeout tm))
(when (and @active f)
(try
(f)
(catch Exception e
(log/error e "Deferred function crash")))))
cancel)))
(defn schedule!
"Schedule the processing of a specific action in the runtime atom. This is a no-op if the item is already scheduled.
When the timeout arrives it runs the given action and sets the given flag back to false.
- `scheduled-key` - The runtime flag that tracks scheduling for the processing.
- `action` - The function to run when the scheduled time comes.
- `tm` - Number of ms to delay (default 0)."
([app scheduled-key action tm]
[:com.fulcrologic.fulcro.application/app keyword? fn? int? => any?]
(let [{:com.fulcrologic.fulcro.application/keys [runtime-atom]} app]
(when-not (get @runtime-atom scheduled-key)
(swap! runtime-atom assoc scheduled-key true)
(defer (fn []
(swap! runtime-atom assoc scheduled-key false)
(action app)) tm))))
([app scheduled-key action]
[:com.fulcrologic.fulcro.application/app keyword? fn? => any?]
(schedule! app scheduled-key action 0)))
(let [raf #?(:clj #(defer % 16)
:cljs (if (exists? js/requestAnimationFrame)
js/requestAnimationFrame
#(defer % 16)))]
(defn schedule-animation!
"Schedule the processing of a specific action in the runtime atom on the next animation frame.
- `scheduled-key` - The runtime flag that tracks scheduling for the processing.
- `action` - The function to run when the scheduled time comes."
([app scheduled-key action]
[:com.fulcrologic.fulcro.application/app keyword? fn? => any?]
#?(:clj (action)
:cljs (let [{:com.fulcrologic.fulcro.application/keys [runtime-atom]} app]
(when-not (get @runtime-atom scheduled-key)
(swap! runtime-atom assoc scheduled-key true)
(let [f (fn []
(swap! runtime-atom assoc scheduled-key false)
(action))]
(raf f))))))))