在Clojure中,使用core.async通道来消费http-kit的POST结果是否明智?

9

我是新手使用Clojure,正在编写一个库将POST结果发送到服务器进行响应。我通过将响应放入core.async通道来消费响应。这样做是否合理或者有更好的方法?

以下是我所做的工作的高级概述:

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

这是我实际使用的代码: https://github.com/gilmaso/btc-trading/blob/master/src/btc_trading/btc_china.clj#L63

它可以工作,但我很难验证是否这是正确的方法。

1个回答

10

core.async 很强大,但在协调更复杂的异步操作时表现得尤为出色。如果您总是希望阻塞响应,我建议使用一个 promise,因为它更简单:

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

如果您想使用通道(channel)工作,代码可以进行一些清理。重要的是,您不需要将所有内容都包装在go块中;go协调异步执行非常出色,但最终,通道就是一个通道。

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

谢谢您的周到回复!我决定使用promise / deliver。我曾经有一个奇怪的想法,认为它会阻塞我的主线程,但我错了。已推送! - gilmaso

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接