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

3.3k views Asked by At

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.

1

There are 1 answers

1
Beyamor On BEST ANSWER

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))))