当使用clojure.core.async时,有没有办法让一个频道等待第一个项目放在上面,然后等待一小段时间,然后获取当前频道上的所有项目(可能在等待的时候到了,并且所有这些都没有阻塞?
即。有没有办法实现get-available-items
:
(defn delayer [ch ch2]
(go (loop []
(when-let [v (<! ch)]
(<! (timeout 500))
(let [vs (get-available-items ch)
items (cons v vs)]
(>! ch2 items))
(recur)))))
基本上,像Java中的BlockingQueue.drain。
答案 0 :(得分:6)
有计划offer this feature有频道,但现在您可以通过以下方式检查频道上是否存在某些内容:
(alts!! [my-chan] :default :nothing-immediately-in-chan)
通过迭代你可以不加阻塞地排出一个频道。
PS:特别感谢tbaldridge和julianlevis在#clojure帮助这个
答案 1 :(得分:2)
您可以在相同的超时频道上进行操作,直到用完&#34;等待时间&#34;,同时收集任何传入的值。
这些似乎有效:
(require '[clojure.core.async :as a :refer [<! >! go chan]])
(defn delayer [in out]
(a/go-loop []
(when-let [v (<! in)]
(loop [batch [v] timeout-ch (a/timeout 500)]
(let [[v ch] (a/alts! [in timeout-ch])]
(if (= in ch)
(recur (conj batch v) timeout-ch)
(>! out batch))))
(recur))))
请注意,我们只创建一次超时通道,然后重复使用它。一个简单的测试来证明它的工作原理:
(def out (chan))
(def in (chan))
(delayer in out)
; print batches as soon as available
(a/go-loop []
(>pprint (str (java.util.Date.) (<! out)))
(recur))
; put a value every 100 millis
(a/go-loop [i 100]
(when-not (zero? i)
(<! (a/timeout 100))
(>! in i)
(recur (dec i))))