带有 core.async 的节流功能

Ant*_*ald 6 clojure clojurescript core.async

应该限制​​函数可能执行的次数。所以在调用一个函数之后,在一段时间内任何重复的调用都应该被忽略。如果在此期间有 where 调用,则应在时间段之后执行最后一个。

这是我使用 core.async 的方法。这里的问题是,额外的调用正在通道 c 中汇总。我需要一个内部只有一个位置的通道,它将被 put 覆盖!每次。

(defn throttle [f time]
  (let [c (chan 1)]
    (go-loop []
      (apply f (<! c))
      (<! (timeout time))
      (recur))
    (fn [& args]
      (put! c (if args args [])))))
Run Code Online (Sandbox Code Playgroud)

用法:

(def throttled (throttle #(print %) 4000))
(doseq [x (range 10)]
   (throttled x))

; 0
;... after 4 seconds
; 9
Run Code Online (Sandbox Code Playgroud)

有谁知道如何解决这个问题?

解决方案

(defn throttle [f time]
  (let [c (chan (sliding-buffer 1))]
    (go-loop []
      (apply f (<! c))
      (<! (timeout time))
      (recur))
    (fn [& args]
      (put! c (or args [])))))
Run Code Online (Sandbox Code Playgroud)

Art*_*ldt 3

要解决您的频道问题,您可以使用带有滑动缓冲区的 chan:

user> (require '[clojure.core.async :as async])
nil
user> (def c (async/chan (async/sliding-buffer 1)))
#'user/c
user> (async/>!! c 1)
true
user> (async/>!! c 2)
true
user> (async/>!! c 3)
true
user> (async/<!! c)
3
Run Code Online (Sandbox Code Playgroud)

这样,只有最后放入通道的值才会在下一个时间间隔被计算。