Количество возможных исполнений функции должно быть ограничено. Таким образом, после вызова функции любой повторный вызов следует игнорировать в течение определенного периода времени. Если в это время есть вызовы, последний должен быть выполнен после периода времени.
Вот мой подход к 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 [])))))
Применение:
(def throttled (throttle #(print %) 4000))
(doseq [x (range 10)]
(throttled x))
; 0
;... after 4 seconds
; 9
Кто-нибудь знает, как это исправить?
Решение
(defn throttle [f time]
(let [c (chan (sliding-buffer 1))]
(go-loop []
(apply f (<! c))
(<! (timeout time))
(recur))
(fn [& args]
(put! c (or args [])))))