我有一些长时间运行的进程,它会在进程完成时返回一个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))))))
答案 0 :(得分: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和分析器?