throttle m.route redraws

This commit is contained in:
Leo Horie 2016-12-04 01:53:39 -05:00
parent 7368cf6f26
commit 2ffd2fb7e4
9 changed files with 161 additions and 119 deletions

View file

@ -3,27 +3,6 @@
var Vnode = require("../render/vnode")
module.exports = function(redrawService) {
function throttle(callback) {
//60fps translates to 16.6ms, round it down since setTimeout requires int
var time = 16
var last = 0, pending = null
var timeout = typeof requestAnimationFrame === "function" ? requestAnimationFrame : setTimeout
return function() {
var now = Date.now()
if (last === 0 || now - last >= time) {
last = now
callback()
}
else if (pending === null) {
pending = timeout(function() {
pending = null
callback()
last = Date.now()
}, time - (now - last))
}
}
}
return function(root, component) {
if (component === null) {
redrawService.render(root, [])
@ -33,10 +12,10 @@ module.exports = function(redrawService) {
if (component.view == null) throw new Error("m.mount(element, component) expects a component, not a vnode")
var run = throttle(function() {
var run = function() {
redrawService.render(root, Vnode(component))
})
}
redrawService.subscribe(root, run)
run()
redrawService.redraw()
}
}

View file

@ -2,6 +2,27 @@
var coreRenderer = require("../render/render")
function throttle(callback) {
//60fps translates to 16.6ms, round it down since setTimeout requires int
var time = 16
var last = 0, pending = null
var timeout = typeof requestAnimationFrame === "function" ? requestAnimationFrame : setTimeout
return function() {
var now = Date.now()
if (last === 0 || now - last >= time) {
last = now
callback()
}
else if (pending === null) {
pending = timeout(function() {
pending = null
callback()
last = Date.now()
}, time - (now - last))
}
}
}
module.exports = function($window) {
var renderService = coreRenderer($window)
renderService.setEventCallback(function(e) {
@ -11,7 +32,7 @@ module.exports = function($window) {
var callbacks = []
function subscribe(key, callback) {
unsubscribe(key)
callbacks.push(key, callback)
callbacks.push(key, throttle(callback))
}
function unsubscribe(key) {
var index = callbacks.indexOf(key)

View file

@ -17,11 +17,11 @@ module.exports = function($window, redrawService) {
current.resolve = null
redrawService.render(root, current.render(Vnode(component, undefined, params)))
}
var run = routeService.defineRoutes(routes, function(component, params, path, route, isRouteChange) {
var run = routeService.defineRoutes(routes, function(component, params, path, route, isAction) {
if (component.view) render({}, component, params, path)
else {
if (component.onmatch) {
if (isRouteChange === false && current.path === path || current.resolve != null) render(current, current.component, params)
if (isAction === false && current.path === path || current.resolve != null) render(current, current.component, params)
else {
current.resolve = function(resolved) {
render(component, resolved, params, path)

View file

@ -221,14 +221,16 @@ o.spec("mount", function() {
mount(root, {view: function() {i++}})
var before = i
redrawService.redraw()
redrawService.redraw()
redrawService.redraw()
redrawService.redraw()
var after = i
setTimeout(function(){
o(before).equals(1)
o(after).equals(1)
o(before).equals(1) // mounts synchronously
o(after).equals(1) // throttles rest
o(i).equals(2)
done()
},40)

View file

@ -17,11 +17,13 @@ o.spec("redrawService", function() {
redrawService.redraw()
})
o("should run a single renderer entry", function() {
o("should run a single renderer entry", function(done) {
var spy = o.spy()
redrawService.subscribe(root, spy)
o(spy.callCount).equals(0)
redrawService.redraw()
o(spy.callCount).equals(1)
@ -30,10 +32,15 @@ o.spec("redrawService", function() {
redrawService.redraw()
redrawService.redraw()
o(spy.callCount).equals(4)
o(spy.callCount).equals(1)
setTimeout(function() {
o(spy.callCount).equals(2)
done()
}, 20)
})
o("should run all renderer entries", function() {
o("should run all renderer entries", function(done) {
var el1 = $document.createElement("div")
var el2 = $document.createElement("div")
var el3 = $document.createElement("div")
@ -53,9 +60,17 @@ o.spec("redrawService", function() {
redrawService.redraw()
o(spy1.callCount).equals(2)
o(spy2.callCount).equals(2)
o(spy3.callCount).equals(2)
o(spy1.callCount).equals(1)
o(spy2.callCount).equals(1)
o(spy3.callCount).equals(1)
setTimeout(function() {
o(spy1.callCount).equals(2)
o(spy2.callCount).equals(2)
o(spy3.callCount).equals(2)
done()
}, 20)
})
o("should stop running after unsubscribe", function() {

View file

@ -608,6 +608,30 @@ o.spec("route", function() {
done()
}, 30)
})
o("throttles", function(done, timeout) {
timeout(200)
var i = 0
$window.location.href = prefix + "/"
route(root, "/", {
"/": {view: function(v) {i++}}
})
var before = i
redrawService.redraw()
redrawService.redraw()
redrawService.redraw()
redrawService.redraw()
var after = i
setTimeout(function(){
o(before).equals(1) // routes synchronously
o(after).equals(2) // redraws synchronously
o(i).equals(3) // throttles rest
done()
},40)
})
})
})
})