From 333e4873d587cdd377e5735584d496b519158d89 Mon Sep 17 00:00:00 2001 From: gered Date: Mon, 9 May 2016 16:29:24 -0400 Subject: [PATCH] adding doc comments and changing some internal use functions to private --- .../net/thegeez/browserchannel/client.cljs | 108 +++++++++++++----- 1 file changed, 82 insertions(+), 26 deletions(-) diff --git a/clj-browserchannel/src/net/thegeez/browserchannel/client.cljs b/clj-browserchannel/src/net/thegeez/browserchannel/client.cljs index 214c12c..b473b3a 100644 --- a/clj-browserchannel/src/net/thegeez/browserchannel/client.cljs +++ b/clj-browserchannel/src/net/thegeez/browserchannel/client.cljs @@ -4,21 +4,17 @@ [dommy.core :refer-macros [sel1]] goog.net.BrowserChannel goog.net.BrowserChannel.Handler - [goog.net.BrowserChannel.State :as bc-state] [goog.events :as events] [goog.debug.Logger.Level :as log-level])) (defonce channel (goog.net.BrowserChannel.)) -(def default-options - {:base "/channel" - :allow-chunked-mode? true - :allow-host-prefix? true - :fail-fast? false - :max-back-channel-retries 3 - :max-forward-channel-retries 2 - :forward-channel-request-timeout (* 20 1000) - :verbose-logging? false}) +; see: https://google.github.io/closure-library/api/source/closure/goog/net/browserchannel.js.src.html#l470 +(def ^:private bch-state-enum-to-keyword + {0 :closed + 1 :init + 2 :opening + 3 :opened}) ; see: https://google.github.io/closure-library/api/source/closure/goog/net/browserchannel.js.src.html#l521 (def ^:private bch-error-enum-to-keyword @@ -34,19 +30,19 @@ 11 :bad-response 12 :active-x-blocked}) -(defn encode-map +(defn- encode-map [data] (doto (js-obj) (aset "__edn" (pr-str data)))) -(defn decode-map +(defn- decode-map [m] (let [m (js->clj m)] (if (contains? m "__edn") (reader/read-string (str (get m "__edn"))) m))) -(defn decode-queued-map +(defn- decode-queued-map [queued-map] (merge {:context (aget queued-map "context") @@ -56,40 +52,52 @@ {:data (reader/read-string (str (get data "__edn")))} {:map data})))) -(defn decode-queued-map-array +(defn- decode-queued-map-array [queued-map-array] (mapv decode-queued-map queued-map-array)) -(defn channel-state [] - (.getState channel)) +(defn channel-state + "returns the current state of the browserchannel connection." + [] + (get bch-state-enum-to-keyword (.getState channel) :unknown)) (defn connected? + "returns true if the browserchannel connection is currently connected." [] - (= (channel-state) bc-state/OPENED)) + (= (channel-state) :opened)) (defn set-debug-log! + "sets the debug log level, and optionally a log output handler function + which defaults to js/console.log" [level & [f]] (doto (.. channel getChannelDebug getLogger) (.setLevel level) (.addHandler (or f #(js/console.log %))))) (defn send-data + "sends data to the server over the forward channel. when the data has + been sent and the server sends an acknowledgement, the optional + on-success callback is invoked." [data & [{:keys [on-success]}]] (if data (.sendMap channel (encode-map data) {:on-success on-success}))) (defn connect! + "starts the browserchannel connection (initiates a connection to the server). + under normal circumstances, your application should not call this directly. + instead your application code should call init!" [& [{:keys [base] :as options}]] (let [state (channel-state)] - (if (or (= state bc-state/CLOSED) - (= state bc-state/INIT)) + (if (or (= state :closed) + (= state :init)) (.connect channel (str base "/test") (str base "/bind"))))) (defn disconnect! + "disconnects and closes the browserchannel connection." [] - (if-not (= (channel-state) bc-state/CLOSED) + (if-not (= (channel-state) :closed) (.disconnect channel))) (defn- get-anti-forgery-token @@ -97,7 +105,7 @@ (if-let [tag (sel1 "meta[name='anti-forgery-token']")] (.-content tag))) -(defn ->handler +(defn- ->handler [{:keys [on-open on-close on-receive on-sent on-error]}] (let [handler (goog.net.BrowserChannel.Handler.)] (set! (.-channelOpened handler) @@ -142,14 +150,62 @@ ;; setting to be able to change, so i think it's worth the risk... (set! goog.net.BrowserChannel/BACK_CHANNEL_MAX_RETRIES (:max-back-channel-retries options))) +(def default-options + "default options that will be applied by init! unless + overridden." + { + ;; base/root url on which to send browserchannel requests to + :base "/channel" + + ;; sets whether chunked mode is allowed. sometimes a useful + ;; debugging tool + :allow-chunked-mode? true + + ;; sets whether the channel allows the user of a subdomain + :allow-host-prefix? true + + ;; when true, this changes the behaviour of the forward channel + ;; (client->server) such that it will not retry failed requests + ;; even once. + :fail-fast? false + + ;; sets the max number of attempts to connect to the server for + ;; back channel (server->client) requests + :max-back-channel-retries 3 + + ;; sets the max number of attempts to connect to the server for + ;; forward channel (client->server) requests + :max-forward-channel-retries 2 + + ;; sets the timeout (in milliseconds) for a forward channel request + :forward-channel-request-timeout (* 20 1000) + + ;; whether to enable somewhat verbose debug logging + :verbose-logging? false + }) + (defn init! + "initializes a browserchannel connection for use, registers your + application event handlers and setting any specified options. + + handler should be a map of event handler functions: + + {:on-open (fn [] ...) + :on-close (fn [pending undelivered] ...) + :on-receive (fn [data] ...) + :on-sent (fn [delivered] ...) + :on-error (fn [error-code] ...) + + :on-open is called when a connection is (re-)established. + :on-close is called when a connection is closed. + :on-receive is called when data is received from the server. + :on-sent is called when data has been successfully sent to + the server ('delivered' is a list of what was sent). + :on-error is only invoked once just before the connection is + closed, and only if there was an error." [handler & [options]] (let [options (merge default-options options)] - (events/listen - js/window "unload" - (fn [] - (disconnect!))) - + (events/listen js/window "unload" #(disconnect!)) (.setHandler channel (->handler handler)) (apply-options! options) (let [csrf-token (get-anti-forgery-token)