【问题标题】:How to use `setTimeout` in ClojureScript?如何在 ClojureScript 中使用`setTimeout`?
【发布时间】:2017-03-31 07:10:40
【问题描述】:

我正在尝试在 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"

我在代码中做错了什么?

【问题讨论】:

    标签: clojure clojurescript reagent


    【解决方案1】:

    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)
    

    【讨论】:

    • 嗯...有没有办法在不使用setTimeout 的情况下实现sleep?这是我的首要目标。不过,我很确定我的问题是 XY 问题,所以我可能不得不发布一个新问题。
    • setTimeout 有什么问题?看看stackoverflow.com/a/39914235/597473。
    • Aww...我看到了那个问题的结果,这有点令人失望。为了真正实现最新解决方案的解决方案,我必须安装另一个库,这很糟糕。还是谢谢!
    【解决方案2】:

    使用 ClojureScript,编写异步代码的最佳方法是使用 CoreAsync 库。在您的情况下,请查看 timeout 函数:

    (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!"]])
    

    【讨论】:

    • 我不得不说这不是最好的方法。语言中有几种处理异步代码的方法。不同的任务需要不同的工具。在这种情况下, core.async 是多余的。此外,它是 core.async 而不是 CoreAsync。
    • @Nek 那么根据您的意见,这个用例中的最佳方法是什么。
    • 设置超时
    【解决方案3】:

    有一种方法可以使用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")
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多