(ns re-frame.handlers (:refer-clojure :exclude [flush]) (:require-macros [cljs.core.async.macros :refer [go-loop go]]) (:require [reagent.core :refer [flush]] [re-frame.db :refer [app-db]] [re-frame.utils :refer [first-in-vector]] [cljs.core.async :refer [chan put! fn (atom {})) (defn register "register a handler for an event" [event-id handler-fn] (when (contains? @id->fn event-id) (warn "Overwriting an event-handler" event-id)) ;; allow it, but warn. (swap! id->fn assoc event-id handler-fn)) ;; -- The Event Conveyor Belt -------------------------------------------------------------------- ;; A channel which moves events from dispatch to handlers. ;; ;; 1. "dispatch" puts events onto this chan, and ;; 2. "router" reads from the chan, and calls associated handlers ;; This enables async handling of events -- which is a good thing. (def ^:private event-chan (chan)) ;; -- router -------------------------------------------------------------------------------------- (defn- handle "Look up the handler for the given event, then call it, passing in 2 parameters." [event-v] (let [event-id (first-in-vector event-v) handler-fn (get @id->fn event-id)] (if (nil? handler-fn) (warn "No event handler registered for event: " event-id ) (handler-fn app-db event-v)))) ;; In a loop, read events from the dispatch channel, and then call the ;; right handler. ;; ;; Because handlers occupy the CPU, before each event is handled, hand ;; back control to the GUI render process, via a ( @db (assoc :undo-description description) mutation-fn validation-fn))))