I am new to clojure and am writing a library that sends post results to a server for a response. I consume the response by placing it onto a core.async channel. Is this sane or is there a better way?
Here is a high level overview of what I am doing:
(defn my-post-request [channel options]
(client/post http://www.example.com options
(fn [{:keys [status headers body error]}] ;; asynchronous handle response
(go (>! channel body)))))
(defn request-caller [options]
(let [channel (chan)]
(my-post-request channel options)
(json/parse-string (<!! (go (<! channel))))))
Here is the actual code that I am using: https://github.com/gilmaso/btc-trading/blob/master/src/btc_trading/btc_china.clj#L63
It works, but I have had a hard time verifying if it is the right way to go about this.
core.async
is powerful, but it really shines when it comes to coordinating more complex asynchronicity. If you always want to block on the response, I'd recommend using a promise
instead since it's a little simpler:
(defn my-post-request [result options]
(client/post http://www.example.com options
(fn [{:keys [status headers body error]}] ;; asynchronous handle response
(deliver result body))))
(defn request-caller [options]
(let [result (promise)]
(my-post-request result options)
; blocks, waiting for the promise to be delivered
(json/parse-string @result)))
If you do want to work with channels, the code can be cleaned up a bit. Importantly, you don't need to wrap everything in a go
block; go
is amazing for coordinating asynchronicity, but ultimately, a channel's a channel:
(defn my-post-request [channel options]
(client/post http://www.example.com options
(fn [{:keys [status headers body error]}] ;; asynchronous handle response
(put! channel body))))
(defn request-caller [options]
(let [channel (chan)]
(my-post-request channel options)
(json/parse-string (<!! channel))))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With