From 5684543b1aa62e5eb1488b28438027569ea0ccb9 Mon Sep 17 00:00:00 2001 From: Mike Thompson Date: Fri, 3 Jun 2016 12:49:49 +1000 Subject: [PATCH] Introduce new API - `remove-post-event-callback` --- CHANGES.md | 16 +++++++++------- src/re_frame/core.cljs | 16 +++++++++++----- src/re_frame/router.cljs | 38 ++++++++++++++++++++++---------------- 3 files changed, 42 insertions(+), 28 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 3eaab4b..17a9307 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,4 +1,4 @@ -## 0.8.0 (XXX) +## 0.8.0 (2016.06.XXXX) Headline: - re-frame subscriptions are now de-duplicated. As a result, some Signal graphs will be much more @@ -20,7 +20,7 @@ Headline: So, these two subscriptions are *not* "the same": `[:some-event 42]` `[:some-event "blah"]`. Even though they involve the same event id, `:some-event`, the query vectors do not test `=`. - + Breaking: - requires Reagent >= 0.6.0 or later. It won't work with <= Reagent 0.5.2. @@ -29,12 +29,12 @@ Breaking: supply alternatives using `re-frame.core/set-loggers!`. With this release, any alternatives you supply will be called with different parameters. - Previously loggers were given a single `str` parameter but now they are expected to act + Previously loggers were called with a single `str` parameter but now they are expected to act like `console.log` itself and take variadic, non string params. Sorry to break things, but we are trying to maximise use of cljs-devtools and information is lost when strings are - output, instead of real data. + output, instead of actual data. - To transition, here's the tweak you can make: + To transition, you'll need to tweak like this: ``` ;; your old log function might have looked like this. Single string parameter. (defn my-logger [s] (do-something-with s)) @@ -42,13 +42,15 @@ Breaking: ;; your new version will have variadic params, and turn them into a string (defn my-logger [& args] (do-something-with (apply str args)) ``` + Of course, you only have to worry about this if you are using `re-frame.core/set-loggers!` to + hook in your own loggers. Otherwise, you have nothing to do. + - - Improvements - XXXX middleware for spec checking of event vectors - XXXX better subscriptions of subscriptions - XXX spec definitions of what subscriptions deliver ?? + - added new API `re-frame.core/remove-post-event-callback`. See doc string. - when an event-handler makes no change to `app-db`, the `debug` middleware now logs a single line saying so, rather than a "group". Makes it slightly easier to grok the absence of change. diff --git a/src/re_frame/core.cljs b/src/re_frame/core.cljs index 4a4e705..6f57a99 100644 --- a/src/re_frame/core.cljs +++ b/src/re_frame/core.cljs @@ -53,16 +53,22 @@ ;; -- Event Procssing Callbacks (defn add-post-event-callback - "Normal users of re-frame can ignore this part of the API. Useful - only to libraries providing 'isomorphic javascript' rendering on - Nodejs or Nashorn. - - Registers a callback function 'f'. + "Registers a callback function 'f'. f will be called after each dispatched event is procecessed f will be called with two parameters: - the event's vector. That which was dispatched orignally. - the further event queue - what is still to be processed. A PersistentQueue. + + This is useful in advanced cases like: + - you are implementing a complex bootstrap pipeline + - you want to create your own handling infrastructure, with perhaps multiple + handlers for the one event, etc. Hook in here. + - a libraries providing 'isomorphic javascript' rendering on Nodejs or Nashorn. " [f] (router/add-post-event-callback re-frame.router/event-queue f)) + +(defn remove-post-event-callback + [f] + (router/remove-post-event-callback re-frame.router/event-queue f)) diff --git a/src/re_frame/router.cljs b/src/re_frame/router.cljs index fbb14c5..ed584c3 100644 --- a/src/re_frame/router.cljs +++ b/src/re_frame/router.cljs @@ -1,7 +1,7 @@ (ns re-frame.router (:require [reagent.core] [re-frame.handlers :refer [handle]] - [re-frame.utils :refer [error]] + [re-frame.utils :refer [warn error]] [goog.async.nextTick])) @@ -72,6 +72,7 @@ ;; -- Public API (enqueue [this event]) (add-post-event-callback [this f]) + (remove-post-event-callback [this f]) ;; -- Implementation via a Finite State Machine (-fsm-trigger [this trigger arg]) @@ -95,16 +96,21 @@ ;; -- API ------------------------------------------------------------------ (enqueue [this event] - ;; put an event into the queue (assumidly because of a dispatch) + ;; put an event into the queue (presumably because of a dispatch) (-fsm-trigger this :add-event event)) (add-post-event-callback [this f] - ;; register a callback to be invoked when events are processed + ;; register a callback to be invoked after events are processed ;; Useful to so-called isomorphic, server-side rendering frameworks + ;; or when you want to do specialised event processing. (set! post-event-callback-fns (conj post-event-callback-fns f))) + (remove-post-event-callback [this f] + (set! post-event-callback-fns (remove #(= % f) post-event-callback-fns))) + ;; -- FSM Implementation --------------------------------------------------- + (-fsm-trigger [this trigger arg] @@ -118,10 +124,10 @@ ;; You should read the following "case" as: ;; [current-FSM-state trigger] -> [new-FSM-state action-fn] ;; - ;; So, the next line should be interpreted as: + ;; So, for example, the next line should be interpreted as: ;; if you are in state ":idle" and a trigger ":add-event" ;; happens, then move the FSM to state ":scheduled" and execute - ;; that "do" fucntion. + ;; that two-part "do" fucntion. [:idle :add-event] [:scheduled #(do (-add-event this arg) (-run-next-tick this))] @@ -137,7 +143,7 @@ [:idle] [:scheduled #(-run-next-tick this)]) - ;; State: :paused (the event metadata :flush-dom has caused a temporary pause in processing) + ;; State: :paused (:flush-dom metadata on an event has caused a temporary pause in processing) [:paused :add-event] [:paused #(-add-event this arg)] [:paused :resume ] [:running #(-resume this)] @@ -156,13 +162,13 @@ (let [event-v (peek queue)] (try (handle event-v) - (catch :default ex - (-fsm-trigger this :exception ex))) - (set! queue (pop queue)) + (set! queue (pop queue)) - ;; Tell all registed callbacks that an event was just processed. - ;; Pass in the event just handled and the new state of the queue - (doseq [f post-event-callback-fns] (f event-v queue)))) + ;; Tell all registed callbacks that an event was just processed. + ;; Pass in the event just handled and the new state of the queue + (doseq [f post-event-callback-fns] (f event-v queue)) + (catch :default ex + (-fsm-trigger this :exception ex))))) (-run-next-tick [this] @@ -220,13 +226,13 @@ (defn dispatch-sync - "Send an event to be processed by the registered handler - immediately. Note: dispatch-sync cannot be called while another - event is being handled. + "Immediately process an event using the registered handler. + + Generally, don't use this. Use \"dispatch\" instead. It + is an error to even try and use it within an event handler. Usage example: (dispatch-sync [:delete-item 42])" [event-v] (handle event-v) nil) ;; Ensure nil return. See https://github.com/Day8/re-frame/wiki/Beware-Returning-False -