Use yield instead of (timeout 0)
(timeout 0) resolves to using js/setTimeout which will actually take 4+ msecs in browsers. This is an eternity. The nextTick approach was proposed by Patrick O'Brien and implemented here. Docs on nextTick from Closure library: Fires the provided callbacks as soon as possible after the current JS execution context. setTimeout(…, 0) takes at least 4ms when called from within another setTimeout(…, 0) for legacy reasons. This will not schedule the callback as a microtask (i.e. a task that can preempt user input or networking callbacks). It is meant to emulate what setTimeout(_, 0) would do if it were not throttled. If you desire microtask behavior, use goog.Promise instead.
This commit is contained in:
parent
3e8f1e1dfa
commit
a2e8c09775
|
@ -4,7 +4,8 @@
|
|||
(:require [reagent.core :refer [flush]]
|
||||
[re-frame.handlers :refer [handle]]
|
||||
[re-frame.utils :refer [warn error]]
|
||||
[cljs.core.async :refer [chan put! <! timeout]]))
|
||||
[cljs.core.async :refer [chan put! <! timeout close!]]
|
||||
[goog.async.nextTick]))
|
||||
|
||||
;; -- The Event Conveyor Belt --------------------------------------------------------------------
|
||||
;;
|
||||
|
@ -25,7 +26,7 @@
|
|||
;; In a perpetual loop, read events from "event-chan", and call the right handler.
|
||||
;;
|
||||
;; Because handlers occupy the CPU, before each event is handled, hand
|
||||
;; back control to the browser, via a (<! (timeout 0)) call.
|
||||
;; back control to the browser, via a (<! (yield)) call.
|
||||
;;
|
||||
;; In some cases, we need to pause for an entire animationFrame, to ensure that
|
||||
;; the DOM is fully flushed, before then calling a handler known to hog the CPU
|
||||
|
@ -34,13 +35,22 @@
|
|||
;; (dispatch ^:flush-dom [:event-id other params])
|
||||
;;
|
||||
|
||||
(defn yield
|
||||
"Yields control to the browser. Faster than (timeout 0).
|
||||
See http://dev.clojure.org/jira/browse/ASYNC-137"
|
||||
[]
|
||||
(let [ch (chan)]
|
||||
(goog.async.nextTick #(close! ch))
|
||||
ch))
|
||||
|
||||
|
||||
(defn router-loop
|
||||
[]
|
||||
(go-loop []
|
||||
(let [event-v (<! event-chan) ;; wait for an event
|
||||
_ (if (:flush-dom (meta event-v)) ;; check the event for metadata
|
||||
(do (flush) (<! (timeout 20))) ;; wait just over one annimation frame (16ms), to rensure all pending GUI work is flushed to the DOM.
|
||||
(<! (timeout 0)))] ;; just in case we are handling one dispatch after an other, give the browser back control to do its stuff
|
||||
(<! (yield)))] ;; just in case we are handling one dispatch after an other, give the browser back control to do its stuff
|
||||
(try
|
||||
(handle event-v)
|
||||
|
||||
|
|
Loading…
Reference in New Issue