I'm trying to make a sleep function in ClojureScript (w/ 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!"]])
For some reason, this doesn't sleep properly - when I click the "Click me!" button, temp-atom increments instantly - when I time it, by putting this after in page:
[:p (time (sleep 3000))]
I get this in the console:
"Elapsed time: 0.015000 msecs"
What did I do wrong in the code?
Javascript's setTimeout function accepts two arguments: function and timeout in milliseconds. Its contract is to run the received function after the timeout passes.
Your code doesn't pass the function you would like to execute after 3 seconds but instead passes a no-op function ((fn [])).
Your sleep function should look like this (and it would be better named timeout or you could just call js/setTimeout directly in your on-click handler):
(defn sleep [f ms]
  (js/setTimeout f ms))
You also need to change how you call this function:
(sleep #(swap! temp-atom inc) 3000)
Or with calling js/setTimeout directly:
(js/setTimeout #(swap! temp-atom inc) 3000)
                        With ClojureScript, the best way to write asynchronous code is with the CoreAsync library. In your case, take a look at the timeout function:
(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!"]])
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With