Split handlers.cljs in two, creating router.cljs
This commit is contained in:
parent
aae13840ba
commit
3540d7da9d
|
@ -2,14 +2,15 @@
|
||||||
(:require
|
(:require
|
||||||
[re-frame.handlers :as handlers]
|
[re-frame.handlers :as handlers]
|
||||||
[re-frame.subs :as subs]
|
[re-frame.subs :as subs]
|
||||||
|
[re-frame.router :as router]
|
||||||
[re-frame.middleware :as middleware]))
|
[re-frame.middleware :as middleware]))
|
||||||
|
|
||||||
|
|
||||||
;; -- API -------
|
;; -- API -------
|
||||||
|
|
||||||
(def register-handler handlers/register)
|
(def register-handler handlers/register)
|
||||||
(def dispatch handlers/dispatch)
|
(def dispatch router/dispatch)
|
||||||
(def dispatch-sync handlers/dispatch-sync)
|
(def dispatch-sync router/dispatch-sync)
|
||||||
|
|
||||||
(def register-sub subs/register)
|
(def register-sub subs/register)
|
||||||
(def subscribe subs/subscribe)
|
(def subscribe subs/subscribe)
|
||||||
|
@ -22,6 +23,7 @@
|
||||||
(def path middleware/path)
|
(def path middleware/path)
|
||||||
(def validate middleware/validate)
|
(def validate middleware/validate)
|
||||||
(def trim-v middleware/trim-v)
|
(def trim-v middleware/trim-v)
|
||||||
|
(def after middleware/after)
|
||||||
; (def log-events middleware/log-events)
|
; (def log-events middleware/log-events)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,14 @@
|
||||||
(ns re-frame.handlers
|
(ns re-frame.handlers
|
||||||
(:refer-clojure :exclude [flush])
|
(:require [re-frame.db :refer [app-db]]
|
||||||
(:require-macros [cljs.core.async.macros :refer [go-loop go]])
|
[re-frame.utils :refer [first-in-vector warn]]))
|
||||||
(:require [reagent.core :refer [flush]]
|
|
||||||
[re-frame.db :refer [app-db]]
|
|
||||||
; [re-frame.middleware :refer [noop]]
|
|
||||||
[re-frame.utils :refer [first-in-vector warn]]
|
|
||||||
[cljs.core.async :refer [chan put! <! timeout]]))
|
|
||||||
|
|
||||||
|
|
||||||
;; -- composing middleware -----------------------------------------------------------------------
|
;; -- composing middleware -----------------------------------------------------------------------
|
||||||
|
|
||||||
(defn comp-middleware
|
(defn comp-middleware
|
||||||
"Given a vector of middleware, filter out any nils, and use \"comp\" to compose them.
|
"Given a vector of middleware, filter out any nils, and use \"comp\" to compose the elements.
|
||||||
v can have nested vectors, and will be flattended before \"comp\" is applied.
|
v can have nested vectors, and will be flattended before \"comp\" is applied.
|
||||||
For convienience, if v turns out to already be a function (assumed to be
|
For convienience, if v a function (assumed to be middleware already), just return it.
|
||||||
middleware), just return it.
|
|
||||||
Filtering out nils allows us to create Middlewhere conditionally like this:
|
Filtering out nils allows us to create Middlewhere conditionally like this:
|
||||||
(comp-middleware [pure (when debug? debug)]) ;; that 'when' might leave a nil
|
(comp-middleware [pure (when debug? debug)]) ;; that 'when' might leave a nil
|
||||||
"
|
"
|
||||||
|
@ -23,21 +17,22 @@
|
||||||
(fn? v) v ;; assumed to be existing middleware
|
(fn? v) v ;; assumed to be existing middleware
|
||||||
(vector? v) (let [v (remove nil? (flatten v))]
|
(vector? v) (let [v (remove nil? (flatten v))]
|
||||||
(cond
|
(cond
|
||||||
(empty? v) (fn [h] h) ;; noop middleware
|
(empty? v) identity ;; noop middleware
|
||||||
(= 1 (count v)) (first v) ;; only one middleware, no composing needed
|
(= 1 (count v)) (first v) ;; only one middleware, no composing needed
|
||||||
:else (apply comp v)))
|
:else (apply comp v)))
|
||||||
:else (assert (vector? v)
|
:else (warn "re-frame: compose expects a vector, got: " v)))
|
||||||
(str "re-frame: compose expects a vector, got: " v))))
|
|
||||||
|
|
||||||
|
|
||||||
;; -- the register of event handlers --------------------------------------------------------------
|
;; -- the register of event handlers --------------------------------------------------------------
|
||||||
|
|
||||||
(def ^:private id->fn (atom {}))
|
(def ^:private id->fn (atom {}))
|
||||||
|
|
||||||
|
|
||||||
(defn lookup-handler
|
(defn lookup-handler
|
||||||
[event-id]
|
[event-id]
|
||||||
(get @id->fn event-id))
|
(get @id->fn event-id))
|
||||||
|
|
||||||
|
|
||||||
(defn register
|
(defn register
|
||||||
"register a handler for an event"
|
"register a handler for an event"
|
||||||
([event-id handler-fn]
|
([event-id handler-fn]
|
||||||
|
@ -46,17 +41,11 @@
|
||||||
(swap! id->fn assoc event-id handler-fn))
|
(swap! id->fn assoc event-id handler-fn))
|
||||||
|
|
||||||
([event-id middleware handler-fn]
|
([event-id middleware handler-fn]
|
||||||
(let [mid-ware (comp-middleware middleware)
|
(let [mid-ware (comp-middleware middleware) ;; compose the middleware
|
||||||
hander-fn (mid-ware handler-fn)]
|
hander-fn (mid-ware handler-fn)] ;; wrap the handler in the middleware
|
||||||
(register event-id hander-fn))))
|
(register event-id hander-fn))))
|
||||||
|
|
||||||
|
|
||||||
;; -- The Event Conveyor Belt --------------------------------------------------------------------
|
|
||||||
;;
|
|
||||||
;; Moves events from "dispatch" to the router loop.
|
|
||||||
;; Allows for the aysnc handling of events.
|
|
||||||
;;
|
|
||||||
(def ^:private event-chan (chan)) ;; TODO: set buffer size?
|
|
||||||
|
|
||||||
|
|
||||||
;; -- lookup and call -----------------------------------------------------------------------------
|
;; -- lookup and call -----------------------------------------------------------------------------
|
||||||
|
@ -76,50 +65,3 @@
|
||||||
(warn "re-frame: no event handler registered for: \"" event-id "\". Ignoring.") ;; TODO: make exception
|
(warn "re-frame: no event handler registered for: \"" event-id "\". Ignoring.") ;; TODO: make exception
|
||||||
(handler-fn app-db event-v))))
|
(handler-fn app-db event-v))))
|
||||||
|
|
||||||
|
|
||||||
;; -- router loop ---------------------------------------------------------------------------------
|
|
||||||
;;
|
|
||||||
;; In a perpretual loop, read events from the dispatch channel, and route them
|
|
||||||
;; to the right handler.
|
|
||||||
;;
|
|
||||||
;; Because handlers occupy the CPU, before each event is handled, hand
|
|
||||||
;; back control to the browser, via a (<! (timeout 0)) call.
|
|
||||||
;;
|
|
||||||
;; In odd cases, we need to pause for an entire annimationFrame, to ensure that
|
|
||||||
;; the DOM is fully flushed, before then calling a handler known to hog the CPU
|
|
||||||
;; for an extended period. In such a case, the event should be laballed with metadata
|
|
||||||
;; Example usage (notice the ":flush-dom" metadata):
|
|
||||||
;; (dispatch ^:flush-dom [:event-id other params])
|
|
||||||
;;
|
|
||||||
;; router loop
|
|
||||||
(go-loop []
|
|
||||||
(let [event-v (<! event-chan) ;; wait for an event
|
|
||||||
_ (if (:flush-dom (meta event-v)) ;; check the event for metadata
|
|
||||||
(do (flush) (<! (timeout 20))) ;; wait just over one annimation frame (16ms), to rensure all pending GUI work is flushed to the DOM.
|
|
||||||
(<! (timeout 0)))] ;; just in case we are handling one dispatch after an other, give the browser back control to do its stuff
|
|
||||||
(handle event-v)
|
|
||||||
(recur)))
|
|
||||||
|
|
||||||
|
|
||||||
;; -- dispatch ------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
(defn dispatch
|
|
||||||
"Send an event to be processed by the registered handler.
|
|
||||||
|
|
||||||
Usage example:
|
|
||||||
(dispatch [:delete-item 42])
|
|
||||||
"
|
|
||||||
[event-v]
|
|
||||||
(if (nil? event-v)
|
|
||||||
(warn "re-frame: \"dispatch\" is ignoring a nil event.") ;; nil would close the channel
|
|
||||||
(put! event-chan event-v))
|
|
||||||
nil) ;; Ensure nil return. See https://github.com/Day8/re-frame/wiki/Returning-False
|
|
||||||
|
|
||||||
|
|
||||||
;; TODO: remove sync handling. I don't like it much, even for testing.
|
|
||||||
(defn dispatch-sync
|
|
||||||
"Invoke the event handler sycronously, avoiding the async-inducing use of core.async/chan"
|
|
||||||
[event-v]
|
|
||||||
(handle event-v))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
(ns re-frame.router
|
||||||
|
(:refer-clojure :exclude [flush])
|
||||||
|
(:require-macros [cljs.core.async.macros :refer [go-loop go]])
|
||||||
|
(:require [reagent.core :refer [flush]]
|
||||||
|
[re-frame.handlers :refer [handle]]
|
||||||
|
[re-frame.utils :refer [warn]]
|
||||||
|
[cljs.core.async :refer [chan put! <! timeout]]))
|
||||||
|
|
||||||
|
;; -- The Event Conveyor Belt --------------------------------------------------------------------
|
||||||
|
;;
|
||||||
|
;; Moves events from "dispatch" to the router loop.
|
||||||
|
;; Using core.async means we can have the aysnc handling of events.
|
||||||
|
;;
|
||||||
|
(def ^:private event-chan (chan)) ;; TODO: set buffer size?
|
||||||
|
|
||||||
|
|
||||||
|
;; -- router loop ---------------------------------------------------------------------------------
|
||||||
|
;;
|
||||||
|
;; In a perpretual loop, read events from "event-chan", and call the right handler.
|
||||||
|
;;
|
||||||
|
;; Because handlers occupy the CPU, before each event is handled, hand
|
||||||
|
;; back control to the browser, via a (<! (timeout 0)) call.
|
||||||
|
;;
|
||||||
|
;; In some cases, we need to pause for an entire annimationFrame, to ensure that
|
||||||
|
;; the DOM is fully flushed, before then calling a handler known to hog the CPU
|
||||||
|
;; for an extended period. In such a case, the event should be laballed with metadata
|
||||||
|
;; Example usage (notice the ":flush-dom" metadata):
|
||||||
|
;; (dispatch ^:flush-dom [:event-id other params])
|
||||||
|
;;
|
||||||
|
(go-loop []
|
||||||
|
(let [event-v (<! event-chan) ;; wait for an event
|
||||||
|
_ (if (:flush-dom (meta event-v)) ;; check the event for metadata
|
||||||
|
(do (flush) (<! (timeout 20))) ;; wait just over one annimation frame (16ms), to rensure all pending GUI work is flushed to the DOM.
|
||||||
|
(<! (timeout 0)))] ;; just in case we are handling one dispatch after an other, give the browser back control to do its stuff
|
||||||
|
(try
|
||||||
|
(handle event-v)
|
||||||
|
(catch js/Object e (.error js/console e))) ;; exceptions are a special kind of rubbish you are in a goloop. So catch it here and print.
|
||||||
|
(recur)))
|
||||||
|
|
||||||
|
|
||||||
|
;; -- dispatch ------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(defn dispatch
|
||||||
|
"Send an event to be processed by the registered handler.
|
||||||
|
|
||||||
|
Usage example:
|
||||||
|
(dispatch [:delete-item 42])
|
||||||
|
"
|
||||||
|
[event-v]
|
||||||
|
(if (nil? event-v)
|
||||||
|
(warn "re-frame: \"dispatch\" is ignoring a nil event.") ;; nil would close the channel
|
||||||
|
(put! event-chan event-v))
|
||||||
|
nil) ;; Ensure nil return. See https://github.com/Day8/re-frame/wiki/Returning-False
|
||||||
|
|
||||||
|
|
||||||
|
;; TODO: remove sync handling. I don't like it much, even for testing.
|
||||||
|
(defn dispatch-sync
|
||||||
|
"Invoke the event handler sycronously, avoiding the async-inducing use of core.async/chan"
|
||||||
|
[event-v]
|
||||||
|
(handle event-v))
|
||||||
|
|
||||||
|
|
|
@ -1,27 +1,27 @@
|
||||||
(ns re-frame.utils)
|
(ns re-frame.utils)
|
||||||
|
|
||||||
|
|
||||||
(defn warn
|
(defn warn
|
||||||
[& args]
|
[& args]
|
||||||
(.warn js/console (apply str args)))
|
(.warn js/console (apply str args)))
|
||||||
|
|
||||||
(defn dbg
|
(defn dbg
|
||||||
[& args]
|
[& args]
|
||||||
(.debug js/console (apply str args)))
|
(.debug js/console (apply str args)))
|
||||||
|
|
||||||
(defn log
|
(defn log
|
||||||
[& args]
|
[& args]
|
||||||
(.log js/console (apply str args)))
|
(.log js/console (apply str args)))
|
||||||
|
|
||||||
(defn group
|
(defn group
|
||||||
[& args]
|
[& args]
|
||||||
(.group js/console (apply str args)))
|
(.group js/console (apply str args)))
|
||||||
|
|
||||||
(defn groupEnd
|
(defn groupEnd
|
||||||
[]
|
[]
|
||||||
(.groupEnd js/console))
|
(.groupEnd js/console))
|
||||||
|
|
||||||
(defn first-in-vector
|
(defn first-in-vector
|
||||||
[v]
|
[v]
|
||||||
(if (vector? v)
|
(if (vector? v)
|
||||||
(first v)
|
(first v)
|
||||||
|
|
Loading…
Reference in New Issue