简体   繁体   English

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

[英]Add delay in clojure.core.async

When using clojure.core.async , is there a way to have one channel wait for the first item to be put on it, then wait some small amount of time, then get all the items currently on the channel (that could have arrived while waiting) and get all of them without blocking? 当使用clojure.core.async时 ,有没有办法让一个频道等待第一个项目放在上面,然后等待一小段时间,然后获取当前频道上的所有项目(可能已到达等待)并让所有这些都没有阻塞?

Ie is there a way to implement get-available-items : 即有一种方法来实现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)))))

Basically, something like BlockingQueue.drain in Java. 基本上,像Java中的BlockingQueue.drain

There are plans to offer this feature with channels, though for now you can check for the presence of something on a channel with: 有计划通过频道提供此功能 ,但现在您可以通过以下方式检查频道上是否存在某些内容:

(alts!! [my-chan] :default :nothing-immediately-in-chan)

by iterating that you can drain a channel without blocking. 通过迭代,您可以在不阻塞的情况下排空通道。

PS: extra thanks to tbaldridge and julianlevis on #clojure for helping with this one PS:额外感谢tbaldridge和julianlevis在#clojure帮助这个

You can just alt on the same timeout channel until you run out of "waiting time", collecting any incoming values meanwhile. 您可以在相同的超时通道上进行操作,直到用完“等待时间”,同时收集任何传入的值。

These seems to work: 这似乎工作:

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

Notice that we create the timeout channel just once and we reuse it. 请注意,我们只创建一次超时通道,然后重用它。 A simple test to prove that it works: 一个简单的测试来证明它的工作原理:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM