[英]How to use `setTimeout` in ClojureScript?
我正在嘗試在 ClojureScript(帶試劑)中創建睡眠功能:
(ns cljweb.webpage
(:require [reagent.core :as reagent]))
(def temp-atom (reagent/atom 0))
(defn sleep [msec]
(js/setTimeout (fn []) msec))
(defn page []
[:div
[:p @temp-atom]
[:button
{:on-click
(fn []
(sleep 3000)
(swap! temp-atom inc))}
"Click me!"]])
出於某種原因,這不能正常睡眠 - 當我點擊“點擊我!” 按鈕, temp-atom
立即增加 - 當我計時時,將它放在page
:
[:p (time (sleep 3000))]
我在控制台中得到這個:
"Elapsed time: 0.015000 msecs"
我在代碼中做錯了什么?
Javascript 的setTimeout
函數接受兩個參數:函數和超時(以毫秒為單位)。 它的合約是在超時過后運行接收到的函數。
您的代碼沒有傳遞您想在 3 秒后執行的函數,而是傳遞一個無操作函數 ( (fn [])
)。
你的sleep
函數應該是這樣的(最好命名為timeout
或者你可以直接在你的點擊處理程序中調用js/setTimeout
):
(defn sleep [f ms]
(js/setTimeout f ms))
您還需要更改調用此函數的方式:
(sleep #(swap! temp-atom inc) 3000)
或者直接調用js/setTimeout
:
(js/setTimeout #(swap! temp-atom inc) 3000)
使用 ClojureScript,編寫異步代碼的最佳方式是使用CoreAsync庫。 在你的情況下,看看超時函數:
(ns cljweb.webpage
(:use-macros [cljs.core.async.macros :only [go]]
(:require [reagent.core :as reagent]
[cljs.core.async :refer [<! timeout]]))
(def temp-atom (reagent/atom 0))
(defn page []
[:div
[:p @temp-atom]
[:button
{:on-click
(fn []
(go
(<! (timeout 3000))
(swap! temp-atom inc)))}
"Click me!"]])
有一種方法可以使用goog.async.Debouncer實現此類功能
下面是一個例子:
(ns example.utils
(:require [goog.async.Debouncer]))
(defn debounce [f interval]
(let [dbnc (goog.async.Debouncer. f interval)]
(fn [& args] (.apply (.-fire dbnc) dbnc (to-array args)))))
(defn save-input! [input]
(js/console.log "Saving input" input))
(def save-input-debounced!
(debounce save-input! 3000))
(save-input-debounced! "hi")
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.