Last active
January 23, 2020 05:45
-
-
Save pangloss/6002224 to your computer and use it in GitHub Desktop.
ClojureScript XHR with core.async.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns xn.test | |
(:require-macros [cljs.core.async.macros :refer [go alts!]] | |
(:require [xn.core :as xn] | |
[xn.util :as u] | |
[cljs.core.async :refer [<! take!]] | |
[xn.xhr :refer [request-body request-records chain-req]])) | |
(def sample-app | |
(reify | |
xn/Application | |
(token [_] "sample 16qqLstdtzyRjWA4zxxE") | |
(base-url [_] "http://localhost:8080/v1"))) | |
(defn show-req [[r ok err]] | |
(take! ok #(.log js/console "ok:" (str %))) | |
(take! err #(.log js/console "err:" (str %)))) | |
(defn g1 [] | |
(show-req (xn/get sample-app :url "/account"))) | |
(defn g2 [] | |
(show-req (chain-req (xn/get sample-app :url "/account") (comp str keys)))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns ^{:doc "Make network requests. | |
Based on: | |
https://github.com/brentonashworth/one | |
/blob/934df802a55cf340740cabc29a129a9d29073733 | |
/src/lib/cljs/one/browser/remote.cljs"} | |
xn.xhr | |
(:use [xn.util :only [map->obj cancel]] | |
[cljs.reader :only [read-string]]) | |
(:require [clojure.browser.event :as event] | |
[goog.net.XhrManager :as manager] | |
[cljs.core.async :as async :refer [<! >! chan close! take! put!]]) | |
(:require-macros | |
[cljs.core.async.macros :as m :refer [go]])) | |
(def method-map {:get "GET" :put "PUT" :post "POST" :patch "PATCH" ; :delete "DELETE" | |
; domain-specific methods: | |
:read "GET" :create "PUT" :update "PATCH" :run "POST" :delete "DELETE"}) | |
(def ^:private | |
*xhr-manager* | |
(goog.net.XhrManager. nil (js-obj "accept" "text/edn") nil nil 5000)) | |
(defn read-response [response] | |
(let [body (.getResponseText response)] | |
(cond | |
(empty? body) nil | |
(string? body) (read-string body) | |
:else body))) | |
(defn handle-response [body err] | |
(fn [e] | |
; Could trigger other global events here if needed... | |
(if (.isSuccess e/target) | |
(do | |
(put! body (read-response e/target)) | |
(close! body) | |
(close! err)) | |
(do | |
(put! err (or (read-response e/target) "error")) | |
(close! body) | |
(close! err))))) | |
(defn request-body | |
"Asynchronously make a network request for the resource at url. The | |
entry for `:event` contains an instance of the `goog.net.XhrManager.Event`. | |
Other allowable keyword arguments are `:method`, `:content`, `:headers`, | |
`:priority`, `:retries`, and `:timeout`. `:method` defaults to \"GET\" and `:retries` | |
defaults to `0`. `:timout` may be a number of milliseconds or a timeout channel. | |
Returns [request body err] where body and err are channels" | |
[url & {:keys [method body headers priority retries id timeout] | |
:or {method :get | |
retries 0}}] | |
(let [body (chan 1) err (chan 1)] | |
(if-let [req (.send *xhr-manager* | |
id | |
url | |
(method-map method) | |
body | |
(map->obj headers) | |
priority | |
(handle-response body err) | |
retries)] | |
#_(let [timeout (if (number? timeout) (async/timeout timeout) timeout)] | |
(take! timeout (fn [] (cancel req)))) ; <- should cause a failure response...? | |
[req body err]))) | |
(defn request-records [& args] | |
(let [[req body err] (apply request-body args) | |
records(chan)] | |
(go | |
(when-let [data (<! body)] | |
(if (sequential? data) | |
(doseq [record data] (>! records record)) | |
(>! records data)) | |
(close! records))) | |
[req records err])) | |
(defn chain-req | |
([req ok-fn] | |
(chain-req req ok-form identity)) | |
([[req ok err] ok-fn err-fn] | |
[req | |
(go (ok-fn (<! ok))) | |
(go (err-fn (<! err)))])) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment