Skip to content

Commit fd3aef9

Browse files
committed
Betters inject api for re-frame idomatic
1 parent c23331c commit fd3aef9

File tree

1 file changed

+57
-48
lines changed

1 file changed

+57
-48
lines changed

src/jtk_dvlp/re_frame/async_coeffects.cljs

Lines changed: 57 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,11 @@
7070
(defonce ^:private !results
7171
(atom {}))
7272

73-
(def !global-error-dispatch
73+
(def ^:private !global-error-dispatch
7474
(atom nil))
7575

7676
(def set-global-error-dispatch!
77-
"Sets global error dispatch to prevent using advanced structure for `inject-acofx`."
77+
"Sets global error dispatch."
7878
(partial reset! !global-error-dispatch))
7979

8080
(defn- fx-handler-run?
@@ -177,30 +177,71 @@
177177
(normalize-acofx cofx)]]
178178
(assoc cofx :data-id id))))
179179

180+
(defn inject-acofxs
181+
"Give as much acofxs as you want as vector or map to compute async (pseudo parallel) values. Use map keys to rename keys within event coeffects map. For further reading see `inject-acofx`."
182+
([acofxs]
183+
(inject-acofxs acofxs nil))
184+
185+
([acofxs {:keys [error-dispatch] :as opts}]
186+
187+
(let [inject-id
188+
(random-uuid)
189+
190+
acofxs-n-options
191+
(->> acofxs
192+
(normalize-acofxs)
193+
(assoc opts :id inject-id, :acofxs))]
194+
195+
(->interceptor
196+
:id
197+
:acoeffects
198+
199+
:before
200+
(fn [context]
201+
(let [dispatch-id
202+
(or (some-> context (:coeffects) (:event) (meta) (::dispatch-id))
203+
(random-uuid))
204+
205+
context
206+
(assoc-in context [:acoeffects :dispatch-id] dispatch-id)]
207+
208+
(if-let [result (get-in @!results [dispatch-id inject-id])]
209+
(update context :coeffects merge result)
210+
(run-acofxs-n-abort-event! context acofxs-n-options))))
211+
212+
:after
213+
(fn [context]
214+
(when (fx-handler-run? context)
215+
(->> context
216+
(:acoeffects)
217+
(:dispatch-id)
218+
(swap! !results dissoc)))
219+
context)))))
220+
180221
(defn inject-acofx
181-
"Given async-coeffects (acofxs) returns an interceptor whose `:before` adds to the `:coeffects` (map) by calling a pre-registered 'async coeffect handler' identified by `id`.
222+
"Given an async-coeffect (acofx) returns an interceptor whose `:before` adds to the `:coeffects` (map) by calling a pre-registered 'async coeffect handler' identified by `id`.
182223
183-
Give as much acofxs as you want to compute async (pseudo parallel) values via `id` of the acofx or an vector of `id` and `args`. `args` can be mixed of any val and fns. fns will be applied with coeffects and event. Computed args prepended with coeffects will be applied to acofx handler.
224+
As first argument give the `id` of the acofx or an vector of `id` and `args`. `args` can be mixed of any val and fns. fns will be applied with coeffects and event. Computed args prepended with coeffects will be applied to acofx handler.
184225
185-
Give a map instead of multiple acofxs like `{:acofxs ...}` to carry a `:error-dispatch` vector, see also `set-global-error-dispatch`. `error-dispatch` will be called on error of any acofxs, event will be aborted. `:acofxs` can be given as vector or map. Use map keys to rename keys within event coeffects map.
226+
As second optional argument give a map of options to carry a `:error-dispatch` vector, see also `set-global-error-dispatch`. `error-dispatch` will be called on error, event will be aborted.
186227
187-
The previous association of a `async coeffect handler` with an `id` will have happened via a call to `reg-acofx` - generally on program startup.
228+
The previous association of a `async coeffect handler` with an `id` will have happened via a call to `reg-acofx` - generally on program startup. See also `reg-acofx-by-fx` to reuse effects as coeffects.
188229
189230
Within the created interceptor, this 'looked up' `async coeffect handler` will be called (within the `:before`) with arguments:
190231
191232
- the current value of `:coeffects`
192-
- optionally, the given or computed args by `args` or `args-fn`
233+
- optionally, the given or computed args by `args`
193234
194235
This `coeffect handler` is expected to modify and return its first, `coeffects` argument.
195236
196237
**Example of `inject-acofx` and `reg-acofx` working together**
197238
198239
199-
First - Early in app startup, you register a `async coeffect handler` for `:async-datetime`:
240+
First - Early in app startup, you register a `async coeffect handler` for `:async-now`:
200241
201242
#!clj
202243
(reg-acofx
203-
:async-datetime ;; usage (inject-acofx :async-datetime)
244+
:async-now ;; usage (inject-acofx :async-now)
204245
(fn async-coeffect-handler
205246
[coeffect]
206247
(go
@@ -212,58 +253,26 @@
212253
#!clj
213254
(re-frame.core/reg-event-fx ;; when registering an event handler
214255
:event-id
215-
[ ... (inject-acofx :async-datetime) ... ] ;; <-- create an injecting interceptor
256+
[ ... (inject-acofx :async-now) ... ] ;; <-- create an injecting interceptor
216257
(fn event-handler
217258
[coeffect event]
218-
;;... in here can access (:async-now coeffect) to obtain current async-datetime ...
259+
;;... in here can access (:async-now coeffect) to obtain current async-now ...
219260
)))
220261
221262
**Background**
222263
223264
`coeffects` are the input resources required by an event handler to perform its job. The two most obvious ones are `db` and `event`. But sometimes an event handler might need other resources maybe async resources.
224265
225-
Perhaps an event handler needs data from backend or some other async call.
266+
Perhaps an event handler needs data from backend or some other async api.
226267
227268
If an event handler directly accesses these resources, it stops being pure and, consequently, it becomes harder to test, etc. So we don't want that.
228269
229270
Instead, the interceptor created by this function is a way to 'inject' 'necessary resources' into the `:coeffects` (map) subsequently given to the event handler at call time.
230271
231272
See also `reg-acofx`
232273
"
233-
([& [map-or-acofx :as acofxs]]
234-
235-
(let [inject-id
236-
(random-uuid)
237-
238-
acofxs-n-options
239-
(if (map? map-or-acofx)
240-
(-> map-or-acofx
241-
(update :acofxs normalize-acofxs)
242-
(assoc :id inject-id))
243-
{:id inject-id, :acofxs (normalize-acofxs acofxs)})]
244-
245-
(->interceptor
246-
:id
247-
:acoeffects
248-
249-
:before
250-
(fn [context]
251-
(let [dispatch-id
252-
(or (some-> context (:coeffects) (:event) (meta) (::dispatch-id))
253-
(random-uuid))
274+
([acofx]
275+
(inject-acofx acofx nil))
254276

255-
context
256-
(assoc-in context [:acoeffects :dispatch-id] dispatch-id)]
257-
258-
(if-let [result (get-in @!results [dispatch-id inject-id])]
259-
(update context :coeffects merge result)
260-
(run-acofxs-n-abort-event! context acofxs-n-options))))
261-
262-
:after
263-
(fn [context]
264-
(when (fx-handler-run? context)
265-
(->> context
266-
(:acoeffects)
267-
(:dispatch-id)
268-
(swap! !results dissoc)))
269-
context)))))
277+
([acofx {:keys [error-dispatch] :as opts}]
278+
(inject-acofxs [acofx] opts)))

0 commit comments

Comments
 (0)