簡體   English   中英

如何在 ClojureScript 中使用 `setTimeout`?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM