From 885b3232c3c863cfcbdcc05c0ba0746e56a0cbf6 Mon Sep 17 00:00:00 2001 From: Oliver Gerlich Date: Wed, 18 Jul 2018 23:12:35 +0200 Subject: [PATCH] move debouncing logic to separate Debouncer class, and use it for list view While the normal GUI is re-rendered at most every 100 msec, the list is re-rendered at most every second (since it is very expensive to render). --- webroot/js/gui.js | 29 ++++++++--------------------- webroot/js/lib.js | 28 ++++++++++++++++++++++++++++ webroot/js/view/list.js | 6 ++++++ 3 files changed, 42 insertions(+), 21 deletions(-) diff --git a/webroot/js/gui.js b/webroot/js/gui.js index 2a94e4b..ae75467 100644 --- a/webroot/js/gui.js +++ b/webroot/js/gui.js @@ -1,4 +1,5 @@ import * as domlib from './domlib'; +import * as lib from './lib'; import {MenuView} from './element/menu'; import Navigo from '../node_modules/navigo/lib/navigo'; import View from './view'; @@ -11,8 +12,14 @@ const router = new Navigo(null, true, '#'), export {router}; + let init = false, - currentView = new View(); + currentView = new View(), + debouncer = new lib.Debouncer(GUI_RENDER_DEBOUNCER_TIME, "gui render"); + +export function render () { + debouncer.run(renderView); +} function renderView () { if (!document.body) { @@ -36,26 +43,6 @@ function renderView () { } -let renderDebounceTimer = null, - numRenderCallsSkipped = 0; - -export function render () { - if (renderDebounceTimer == null) { - renderView(); - renderDebounceTimer = window.setTimeout(() => { - renderDebounceTimer = null; - if (numRenderCallsSkipped > 0) { - console.log("skipped " + numRenderCallsSkipped + " render calls; calling render() now"); - numRenderCallsSkipped = 0; - render(); - } - }, GUI_RENDER_DEBOUNCER_TIME); - } else { - console.log("skip rendering"); - numRenderCallsSkipped++; - } -} - export function setView (toView) { currentView.unbind(); currentView = toView; diff --git a/webroot/js/lib.js b/webroot/js/lib.js index f7074fb..a6e724d 100644 --- a/webroot/js/lib.js +++ b/webroot/js/lib.js @@ -23,3 +23,31 @@ export function FromNowAgo(timeString) { time /= 24; return Math.round(time) + ' d'; } + + +/// Suppresses multiple rapid calls to a function, and instead calls the target function when a timeout has elapsed. +export class Debouncer { + constructor (timeoutMsec, description) { + this.timeoutMsec = timeoutMsec; + this.desc = description; + + this.timer = null; + this.numCallsSkipped = 0; + } + + run (actualFunction) { + if (this.timer == null) { + actualFunction(); + this.timer = window.setTimeout(() => { + this.timer = null; + if (this.numCallsSkipped > 0) { + console.log("skipped " + this.numCallsSkipped + " " + this.desc + " calls; running " + this.desc + " now"); + this.numCallsSkipped = 0; + this.run(actualFunction); + } + }, this.timeoutMsec); + } else { + this.numCallsSkipped++; + } + } +}; diff --git a/webroot/js/view/list.js b/webroot/js/view/list.js index 5bb5d57..47ffa03 100644 --- a/webroot/js/view/list.js +++ b/webroot/js/view/list.js @@ -1,5 +1,6 @@ import * as domlib from '../domlib'; import * as gui from '../gui'; +import * as lib from '../lib'; import * as socket from '../socket'; import * as store from '../store'; import config from '../config'; @@ -10,6 +11,7 @@ export class ListView extends View { constructor () { super(); + this.debouncer = new lib.Debouncer(1000, "list render"); const table = domlib.newAt(this.el, 'table'), thead = domlib.newAt(table, 'thead'); @@ -387,6 +389,10 @@ export class ListView extends View { } render () { + this.debouncer.run(this.renderView); + } + + renderView () { if (this.editing && this.tbody) { return; }