在clojure.core.async中添加延​​迟

时间:2015-02-04 04:30:11

标签: asynchronous clojure

当使用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

2 个答案:

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