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).
This commit is contained in:
Oliver Gerlich 2018-07-18 23:12:35 +02:00 committed by Geno
parent 67dd56d71d
commit 885b3232c3
3 changed files with 42 additions and 21 deletions

View File

@ -1,4 +1,5 @@
import * as domlib from './domlib'; import * as domlib from './domlib';
import * as lib from './lib';
import {MenuView} from './element/menu'; import {MenuView} from './element/menu';
import Navigo from '../node_modules/navigo/lib/navigo'; import Navigo from '../node_modules/navigo/lib/navigo';
import View from './view'; import View from './view';
@ -11,8 +12,14 @@ const router = new Navigo(null, true, '#'),
export {router}; export {router};
let init = false, 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 () { function renderView () {
if (!document.body) { 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) { export function setView (toView) {
currentView.unbind(); currentView.unbind();
currentView = toView; currentView = toView;

View File

@ -23,3 +23,31 @@ export function FromNowAgo(timeString) {
time /= 24; time /= 24;
return Math.round(time) + ' d'; 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++;
}
}
};

View File

@ -1,5 +1,6 @@
import * as domlib from '../domlib'; import * as domlib from '../domlib';
import * as gui from '../gui'; import * as gui from '../gui';
import * as lib from '../lib';
import * as socket from '../socket'; import * as socket from '../socket';
import * as store from '../store'; import * as store from '../store';
import config from '../config'; import config from '../config';
@ -10,6 +11,7 @@ export class ListView extends View {
constructor () { constructor () {
super(); super();
this.debouncer = new lib.Debouncer(1000, "list render");
const table = domlib.newAt(this.el, 'table'), const table = domlib.newAt(this.el, 'table'),
thead = domlib.newAt(table, 'thead'); thead = domlib.newAt(table, 'thead');
@ -387,6 +389,10 @@ export class ListView extends View {
} }
render () { render () {
this.debouncer.run(this.renderView);
}
renderView () {
if (this.editing && this.tbody) { if (this.editing && this.tbody) {
return; return;
} }