Skip to content

Commit

Permalink
Betters usability of task data
Browse files Browse the repository at this point in the history
- Changes name to a non namespaced keyword
- Adds ability to modify the task from within the event
- Betters event unregister-and-dispatch-original to work with manual registered tasks
- Tasks subscriptions returns tasks vector instead of map
  • Loading branch information
jtkDvlp committed Sep 22, 2022
1 parent 8e00aae commit 216200d
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 42 deletions.
60 changes: 35 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Interceptor and helpers to register and unregister (background-)tasks (FXs) in y
* events to register / unregister tasks yourself
* helpers to register / unregister tasks into db yourself

Alsoe works for async coeffects injections, see https://github.com/jtkDvlp/re-frame-async-coeffects.
Also works for async coeffects injections, see https://github.com/jtkDvlp/re-frame-async-coeffects.

## Getting started

Expand All @@ -36,50 +36,60 @@ See api docs [![cljdoc badge](https://cljdoc.org/badge/jtk-dvlp/re-frame-tasks)]


(rf/reg-event-fx :some-event
;; give it a name and fx keys to identify the task and effects emitted by this event.
[(tasks/as-task :some-task [:some-fx :some-other-fx])
;; futher more you can give it the handler keys to hang in finishing the tasks effects
;; (tasks/as-task :some-task
;; [[:some-fx :on-done :on-done-with-errors]
;; [:some-other-fx :on-yuhu :on-oh-no]])
;; last but not least supports the special effect :fx giving an path for the fx to monitor.
;; (tasks/as-task :some-task [[[:fx 1] :on-done ,,,] ; you need to give it the index of the effect within :fx vector to monitor.
;; ,,,])
]
;; give it the fx to identify the task emitted by this event
[(tasks/as-task :some-task
[:some-fx
[:some-other-fx :on-done :on-done-with-errors]
[[:fx 1] :on-done]])
(acoeffects/inject-acofx :some-acofx)]
(fn [_ _]
{:some-fx
{:label "Do some fx"
{;; modify your task via fx
::tasks/task
{:this-is-some-task :data}

:some-fx
{,,,
;; you can give the tasks an id (default: uuid), see subscription `:jtk-dvlp.re-frame.tasks/running?` for usage.
:on-success [:some-event-success]
:on-error [:some-event-error]
:on-done [:some-event-completed]}
;; calling this by `:some-fx` will unregister the task via `tasks/as-task`
:on-complete [:some-event-completed]}

:some-other-fx
{,,,
:label "Do some other fx"
;; calling this by some-fx will unregister the task via `tasks/as-task`
;; `:on-done-with-error` will also untergister the task when called by `:some-other-fx`
:on-done [:some-other-event-completed]}}))
:on-done [:some-other-event-completed]}

:fx
[[:some-fx
{:on-success [:some-event-success]
:on-error [:some-event-error]
:on-complete [:some-event-completed]}]

;; same with :fx effect referenzed via path [:fx 1]
[:some-other-fx
{:on-done [:some-other-event-completed]}]]}))

(defn app-view
[]
(let [block-ui?
(rf/subscribe [:jtk-dvlp.re-frame.tasks/running?])

;; for sugar you can give it also a task name to filter the running tasks.
some-important-stuff-running?
(rf/subscribe [:jtk-dvlp.re-frame.tasks/running? :some-important-stuff])

tasks
(rf/subscribe [:jtk-dvlp.re-frame.tasks/tasks])]

(fn []
[:<>
[:div "some app content"]
[:button {:on-click #(rf/dispatch [:some-event])}
"exec some event"]

[:ul "task list"
;; each task is a map with the original event vector plus name and id.
(for [{:keys [:jtk-dvlp.re-frame.tasks/id] :as task} @tasks]
[:ul "task list " (count @tasks)
;; each task is the original fx map plus an `::tasks/id`, the original `event`
;; and the data you carry via `::task` fx from within the event
(for [{:keys [::tasks/id] :as task} @tasks]
^{:key id}
[:li task])]
[:li [:pre (with-out-str (cljs.pprint/pprint task))]])]

(when @block-ui?
[:div "this div blocks the UI if there are running tasks"])])))
Expand Down
11 changes: 8 additions & 3 deletions dev/jtk_dvlp/your_project.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,11 @@
(acoeffects/inject-acofx :some-acofx)]
(fn [_ _]
(println "handler")
{:some-fx
{;; modify your task via fx
::tasks/task
{:this-is-some-task :data}

:some-fx
{,,,
;; you can give the tasks an id (default: uuid), see subscription `:jtk-dvlp.re-frame.tasks/running?` for usage.
:on-success [:some-event-success]
Expand Down Expand Up @@ -162,8 +166,9 @@
"exec some other bad event"]

[:ul "task list " (count @tasks)
;; each task is the original fx map plus an `::tasks/id` and `::tasks/effect`
(for [{:keys [::tasks/id] :as task} (vals @tasks)]
;; each task is the original fx map plus an `::tasks/id`, the original `event`
;; and the data you carry via `::task` fx from within the event
(for [{:keys [::tasks/id] :as task} @tasks]
^{:key id}
[:li [:pre (with-out-str (cljs.pprint/pprint task))]])]

Expand Down
41 changes: 27 additions & 14 deletions src/jtk_dvlp/re_frame/tasks.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
[name-or-task]
(if (map? name-or-task)
name-or-task
{::name name-or-task}))
{:name name-or-task}))

(defn- normalize-effect-key
[effect-key]
Expand Down Expand Up @@ -143,12 +143,14 @@
{:keys [dispatch-id ?error]}
acoeffects

task
{task-id ::id :as task}
(assoc task ::id dispatch-id)]

(if (fx-handler-run? context)
(or
(unregister-by-fxs context task fxs)
(-> context
(interceptor/assoc-effect :db (update-in db [::db :tasks task-id] merge task))
(unregister-by-fxs task fxs))
(interceptor/assoc-effect context :db (unregister db task)))
(-> context
(interceptor/assoc-effect :db (register db task))
Expand Down Expand Up @@ -180,11 +182,13 @@

(defn as-task
"Creates an interceptor to mark an event as task.
Give it a name of the task or map with at least a `::name` key or nil / nothing to use the event name.
Give it a name of the task or map with at least a `:name` key or nil / nothing to use the event name.
Tasks can be used via subscriptions `::tasks` and `::running?`.
Given vector `fxs` will be used to identify effects to monitor for the task. Can be the keyword of the effect or an vector of effect keyword or effect path (to handle special :fx effect) and completion keywords to hang in. Completion keys defaults to `:on-complete`, `:on-success`, `on-failure` and `on-error`. See also `set-global-default-completion-keys!` and `merge-global-default-completion-keys!`.
Within your event handler use `::task` as effect to modify your task data.
Works in combination with https://github.com/jtkDvlp/re-frame-async-coeffects. For async coeffects there is no need to define what to monitor. Coeffects will be monitored automatically."
([]
(as-task nil))
Expand All @@ -204,7 +208,12 @@
(-> name-or-task
(or (task-by-original-event context))
(normalize-task)
(assoc ::event (get-original-event context)))]
(assoc :event (get-original-event context))
(merge (interceptor/get-effect context ::task)))

;; NOTE: ::task fx is only to carry task data
context
(update context :effects dissoc ::task)]

(cond
(includes-acofxs? context)
Expand Down Expand Up @@ -234,11 +243,13 @@
(when original-event-vec
(rf/dispatch (into original-event-vec original-event-args)))

(if (= 1 (get @!task<->fxs-counters id))
(do
(swap! !task<->fxs-counters dissoc id)
(rf/dispatch [::unregister task]))
(swap! !task<->fxs-counters update id dec))))
(if-let [fxs-rest-count (get @!task<->fxs-counters id)]
(if (= 1 fxs-rest-count)
(do
(swap! !task<->fxs-counters dissoc id)
(rf/dispatch [::unregister task]))
(swap! !task<->fxs-counters update id dec))
(rf/dispatch [::unregister task]))))


;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Expand All @@ -251,11 +262,13 @@
(rf/reg-sub ::tasks
:<- [::db]
(fn [{:keys [tasks]}]
tasks))
(vals tasks)))

(rf/reg-sub ::running?
:<- [::tasks]
(fn [tasks [_ name]]
(if name
(->> tasks (vals) (filter #(= (::name %) name)) (first) (some?))
(-> tasks (first) (some?)))))
(-> tasks
(cond->>
name (some #(= (:name %) name)))
(seq)
(some?))))

0 comments on commit 216200d

Please sign in to comment.