2

我有一些长时间运行的进程,当进程完成时,它会返回一个带有结果的 core.async 通道。

现在我想使用带有 HTTP-kit 的长轮询返回该结果。不幸的是,我有点困惑正确的做法是什么。

目前我有一个处理程序(连接到一个路由),它启动处理调用并在完成后发送结果:

(defn handler
  [request]
  (let [c (process request)] ;; long running process that returns a channel
    (http/with-channel request channel
      (http/send! channel {:status 200
                           :body (<!! (go (<! c)))))
      (http/on-close channel (fn [_] (async/close! c))))))

它有效,但我不确定这是否是正确的方法。

编辑因为<!!是阻塞我现在在 go-loop 中尝试一个非阻塞变体

(defn handler
  [request]
  (let [c (process request)]
    (http/with-channel request channel
      (async/go-loop [v (<! c)]
        (http/send! channel {:status 200
                             :body v}))
      (http/on-close channel (fn [_] (async/close! c))))))
4

1 回答 1

1

为什么不在 go 块中的通道上发送?

(http/with-channel request channel
  (go (http/send! channel (<! c))))

<!!是阻塞的 - 所以你的代码直接调用处理程序并没有真正的优势<!! c

(defn handler [request] (let [c (process request)] ;; long running process that returns a channel {:status 200 :body (<!! c)}))


针对问题更新进行编辑:更新后的代码有效- 这是一个功能齐全的命名空间,适用于我:

(ns async-resp.core
  (:require [org.httpkit.server :as http]
            [clojure.core.async :as async :refer (<! >! go chan go-loop close! timeout)]))

(defn process
  [_]
  (let [ch (chan)]
    (go
      (<! (timeout 5000))
      (>! ch "TEST"))
    ch))

(defn test-handler
  [request]
  (let [c (process request)]
    (http/with-channel request channel
      (go-loop [v (<! c)]
        (http/send! channel {:status 200
                             :body v}))
      (http/on-close channel (fn [_] (close! c))))))

(defn run
  []
  (http/run-server test-handler {}))

不过,截至目前,我不得不手动将 tools.analyzer.jvm 依赖项添加到 project.clj - 因为我使用 core.async 按原样编译失败。

检查您是否正在运行最新的 core.async 和分析器?

于 2014-07-03T09:26:38.813 回答