diff --git a/README.md b/README.md index 875c7a64..273d0822 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ app.controller = function() { this.pages = app.PageList(); this.rotate = function() { - this.pages.push(this.pages.shift()) + this.pages().push(this.pages().shift()) }.bind(this) }; diff --git a/docs/getting-started.md b/docs/getting-started.md index 574e2a70..5fb5cc9e 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -376,6 +376,8 @@ m.module(document, todo); Mithril's auto-redrawing system keeps track of controller stability, and only redraws the view once it detects that the controller has finished running all of its code, including asynchronous AJAX payloads. +Also note that this mechanism itself is not asynchronous if it doesn't need to be: Mithril does not need to wait for the next browser repaint frame to redraw - it doesn't even need to wait for the document ready event on the first redraw - it will redraw immediately upon script completion, if able to. + --- ### Summary diff --git a/docs/layout/index.html b/docs/layout/index.html index d7192c7b..86ea805a 100644 --- a/docs/layout/index.html +++ b/docs/layout/index.html @@ -89,7 +89,7 @@ app.controller = function() { this.pages = app.PageList(); this.rotate = function() { - this.pages.push(this.pages.shift()) + this.pages().push(this.pages().shift()) }.bind(this) }; diff --git a/mithril.js b/mithril.js index f2d10db2..f36a54bb 100644 --- a/mithril.js +++ b/mithril.js @@ -284,7 +284,10 @@ Mithril = m = new function app(window) { e = e || event m.startComputation() try {return callback.call(object, e)} - finally {m.endComputation()} + finally { + if (!lastRedrawId) lastRedrawId = -1; + m.endComputation() + } } } @@ -351,8 +354,14 @@ Mithril = m = new function app(window) { m.redraw = function() { var cancel = window.cancelAnimationFrame || window.clearTimeout var defer = window.requestAnimationFrame || window.setTimeout - cancel(lastRedrawId) - lastRedrawId = defer(redraw, 0) + if (lastRedrawId) { + cancel(lastRedrawId) + lastRedrawId = defer(redraw, 0) + } + else { + redraw() + lastRedrawId = defer(function() {lastRedrawId = null}, 0) + } } function redraw() { for (var i = 0; i < roots.length; i++) { @@ -362,6 +371,7 @@ Mithril = m = new function app(window) { computePostRedrawHook() computePostRedrawHook = null } + lastRedrawId = null } var pendingRequests = 0 diff --git a/tests/mithril-tests.js b/tests/mithril-tests.js index b0d54648..1a61a1b6 100644 --- a/tests/mithril-tests.js +++ b/tests/mithril-tests.js @@ -714,12 +714,13 @@ function testMithril(mock) { } }) mock.requestAnimationFrame.$resolve() //teardown - m.redraw() - m.redraw() + m.redraw() //should run synchronously + + m.redraw() //rest should run asynchronously since they're spamming m.redraw() m.redraw() mock.requestAnimationFrame.$resolve() //teardown - return count === 2 + return count === 3 }) //m.route diff --git a/tests/mock.js b/tests/mock.js index 811208df..fe458649 100644 --- a/tests/mock.js +++ b/tests/mock.js @@ -72,7 +72,11 @@ mock.window = new function() { } window.scrollTo = function() {} window.cancelAnimationFrame = function() {} - window.requestAnimationFrame = function(callback) {window.requestAnimationFrame.$callback = callback} + window.requestAnimationFrame = function(callback) { + window.requestAnimationFrame.$callback = callback + return window.requestAnimationFrame.$id++ + } + window.requestAnimationFrame.$id = 1 window.requestAnimationFrame.$resolve = function() { if (window.requestAnimationFrame.$callback) window.requestAnimationFrame.$callback() window.requestAnimationFrame.$callback = null