From 3db7d69849ac17df6f41a1423a87dca8c9f76230 Mon Sep 17 00:00:00 2001 From: Christopher Chedeau Date: Sat, 11 Jan 2020 20:15:41 -0800 Subject: [PATCH] Debounce localstorage save (#328) I profiled dragging and it looks like it takes ~3ms to save to localStorage a smallish scene and we're doing it twice per mousemove. Let's debounce so we don't pay that cost on every mouse move. Stole the implementation from #220 which got reverted. --- src/index.tsx | 8 ++++++-- src/utils.ts | 11 +++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index b2e31690..5f9a82f0 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -28,7 +28,7 @@ import { renderScene } from "./renderer"; import { AppState } from "./types"; import { ExcalidrawElement, ExcalidrawTextElement } from "./element/types"; -import { getDateTime, isInputLike, measureText } from "./utils"; +import { getDateTime, isInputLike, measureText, debounce } from "./utils"; import { KEYS, META_KEY, isArrowKey } from "./keys"; import { findShapeByKey, shapesShortcutKeys } from "./shapes"; @@ -1016,13 +1016,17 @@ export class App extends React.Component<{}, AppState> { } } + private saveDebounced = debounce(() => { + saveToLocalStorage(elements, this.state); + }, 300); + componentDidUpdate() { renderScene(elements, this.rc!, this.canvas!, { scrollX: this.state.scrollX, scrollY: this.state.scrollY, viewBackgroundColor: this.state.viewBackgroundColor }); - saveToLocalStorage(elements, this.state); + this.saveDebounced(); if (history.isRecording()) { history.pushEntry(history.generateCurrentEntry(elements)); history.clearRedoStack(); diff --git a/src/utils.ts b/src/utils.ts index 4043c5a4..32147dc4 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -51,3 +51,14 @@ export function measureText(text: string, font: string) { return { width, height, baseline }; } + +export function debounce( + fn: (...args: T) => void, + timeout: number +) { + let handle = 0; + return (...args: T) => { + clearTimeout(handle); + handle = window.setTimeout(() => fn(...args), timeout); + }; +}