From 7efda2c10bae2babf35c604678c406b065556acc Mon Sep 17 00:00:00 2001 From: Leo Horie Date: Thu, 18 Sep 2014 22:58:59 -0400 Subject: [PATCH] deal with setTimeout properly --- mithril.js | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/mithril.js b/mithril.js index 24cc7581..8c720b90 100644 --- a/mithril.js +++ b/mithril.js @@ -366,7 +366,7 @@ Mithril = m = new function app(window, undefined) { m.startComputation() try {return callback.call(object, e)} finally { - if (!lastRedrawId) lastRedrawId = -1 + if (!lastRedrawId) lastRedrawId = -1 //force asynchronous redraw for event handlers, to prevent double redraw in cases like onkeypress+oninput m.endComputation() } } @@ -439,7 +439,8 @@ Mithril = m = new function app(window, undefined) { return _prop(store) } - var roots = [], modules = [], controllers = [], lastRedrawId = 0, redrawAgain = false, computePostRedrawHook = null, prevented = false + var roots = [], modules = [], controllers = [], lastRedrawId = 0, lastRedrawCallTime = 0, computePostRedrawHook = null, prevented = false + var FRAME_BUDGET = 16 //60 frames per second = 1 call per 16 ms m.module = function(root, module) { var index = roots.indexOf(root) if (index < 0) index = roots.length @@ -463,20 +464,20 @@ Mithril = m = new function app(window, undefined) { m.redraw = function(force) { var cancel = window.cancelAnimationFrame || window.clearTimeout var defer = window.requestAnimationFrame || window.setTimeout + //lastRedrawId is a positive number if a second redraw is requested before the next animation frame + //lastRedrawId is -1 if the redraw is the first one in a event handler (see #151) + //lastRedrawID is null if it's the first redraw and not an event handler if (lastRedrawId && force !== true) { - redrawAgain = true + //when setTimeout: only reschedule redraw if time between now and previous redraw is bigger than a frame, otherwise keep currently scheduled timeout + //when rAF: always reschedule redraw + if (new Date - lastRedrawCallTime > FRAME_BUDGET || defer == window.requestAnimationFrame) { + if (lastRedrawID > 0) cancel(lastRedrawId) + lastRedrawId = defer(redraw, delay) + } } else { redraw() - lastRedrawId = defer(delay, 16) //60 frames per second = 1 call per 16 ms - } - - function delay() { - lastRedrawId = null - if (redrawAgain) { - redrawAgain = false - m.redraw() - } + lastRedrawId = defer(function() {lastRedrawId = null}, delay) } } m.redraw.strategy = m.prop() @@ -490,6 +491,7 @@ Mithril = m = new function app(window, undefined) { computePostRedrawHook = null } lastRedrawId = null + lastRedrawCallTime = new Date m.redraw.strategy("diff") }