Is it sane to use core.async channels to consume http-kit's post results in clojure?
Asked Answered
O

1

9

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.

Oakes answered 12/12, 2013 at 4:4 Comment(0)
G
10

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))))
Gusella answered 12/12, 2013 at 6:6 Comment(1)
Thank you for the thoughtful response! I decided to go with promise/deliver. I had this weird idea that it would block my main thread, but I was wrong about that. Pushed!Oakes

© 2022 - 2024 — McMap. All rights reserved.