如何在ClojureScript中使用`setTimeout`?

Qwe*_*erp 4 clojure clojurescript reagent

我正在尝试在ClojureScript中创建一个睡眠函数(带有Reagent):

(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!"]])
Run Code Online (Sandbox Code Playgroud)

出于某种原因,当我点击"点击我!"时,它无法正常睡眠.按钮,temp-atom立即递增 - 当我计时时,将其放入page:

[:p (time (sleep 3000))]
Run Code Online (Sandbox Code Playgroud)

我在控制台中得到这个:

"Elapsed time: 0.015000 msecs"
Run Code Online (Sandbox Code Playgroud)

我在代码中做错了什么?

Pio*_*dyl 11

Javascript的setTimeout函数接受两个参数:function和timeout(以毫秒为单位).它的合同是在超时通过后运行接收的函数.

您的代码在3秒后没有传递您想要执行的函数,而是通过了无操作函数((fn [])).

你的sleep函数应该是这样的(它会更好地命名,timeout或者你可以js/setTimeout直接在你的on-click处理程序中调用):

(defn sleep [f ms]
  (js/setTimeout f ms))
Run Code Online (Sandbox Code Playgroud)

您还需要更改调用此函数的方式:

(sleep #(swap! temp-atom inc) 3000)
Run Code Online (Sandbox Code Playgroud)

或者js/setTimeout直接打电话:

(js/setTimeout #(swap! temp-atom inc) 3000)
Run Code Online (Sandbox Code Playgroud)

  • 嗯...有没有一种方法可以不用使用setTimeout来达到睡眠状态?那是我的主要目标。我很确定这会使我的问题成为XY问题,因此我可能不得不发布一个新问题。 (2认同)
  • setTimeout有什么问题?看看http://stackoverflow.com/a/39914235/597473。 (2认同)

Ash*_*her 9

使用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!"]])
Run Code Online (Sandbox Code Playgroud)

  • 我不得不说这不是最好的方式.该语言有几种方法可以处理异步代码.不同的任务需要不同的工具 在这种情况下,core.async是一种矫枉过正.此外,它的核心.async不是CoreAsync. (3认同)