From 0e12a8dab9ccec83b91722a8b0a065c0919af98a Mon Sep 17 00:00:00 2001 From: Nolan Lawson Date: Wed, 31 May 2017 06:11:33 -0700 Subject: [PATCH] Improve scheduling of requestIdleCallback tasks (#3477) --- app/javascript/mastodon/components/status.js | 3 +- .../features/ui/util/schedule_idle_task.js | 29 +++++++++++++++++++ package.json | 1 + yarn.lock | 4 +++ 4 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 app/javascript/mastodon/features/ui/util/schedule_idle_task.js diff --git a/app/javascript/mastodon/components/status.js b/app/javascript/mastodon/components/status.js index d35642ede..2abe50f0b 100644 --- a/app/javascript/mastodon/components/status.js +++ b/app/javascript/mastodon/components/status.js @@ -14,6 +14,7 @@ import { FormattedMessage } from 'react-intl'; import emojify from '../emoji'; import escapeTextContentForBrowser from 'escape-html'; import ImmutablePureComponent from 'react-immutable-pure-component'; +import scheduleIdleTask from '../features/ui/util/schedule_idle_task'; class Status extends ImmutablePureComponent { @@ -92,7 +93,7 @@ class Status extends ImmutablePureComponent { const isIntersecting = entry.intersectionRatio > 0; this.setState((prevState) => { if (prevState.isIntersecting && !isIntersecting) { - requestIdleCallback(this.hideIfNotIntersecting); + scheduleIdleTask(this.hideIfNotIntersecting); } return { isIntersecting: isIntersecting, diff --git a/app/javascript/mastodon/features/ui/util/schedule_idle_task.js b/app/javascript/mastodon/features/ui/util/schedule_idle_task.js new file mode 100644 index 000000000..b04d4a8ee --- /dev/null +++ b/app/javascript/mastodon/features/ui/util/schedule_idle_task.js @@ -0,0 +1,29 @@ +// Wrapper to call requestIdleCallback() to schedule low-priority work. +// See https://developer.mozilla.org/en-US/docs/Web/API/Background_Tasks_API +// for a good breakdown of the concepts behind this. + +import Queue from 'tiny-queue'; + +const taskQueue = new Queue(); +let runningRequestIdleCallback = false; + +function runTasks(deadline) { + while (taskQueue.length && deadline.timeRemaining() > 0) { + taskQueue.shift()(); + } + if (taskQueue.length) { + requestIdleCallback(runTasks); + } else { + runningRequestIdleCallback = false; + } +} + +function scheduleIdleTask(task) { + taskQueue.push(task); + if (!runningRequestIdleCallback) { + runningRequestIdleCallback = true; + requestIdleCallback(runTasks); + } +} + +export default scheduleIdleTask; diff --git a/package.json b/package.json index 8bdf6f21b..92221d8e4 100644 --- a/package.json +++ b/package.json @@ -105,6 +105,7 @@ "stringz": "^0.2.0", "style-loader": "^0.16.1", "throng": "^4.0.0", + "tiny-queue": "^0.2.1", "uuid": "^3.0.1", "uws": "^0.14.5", "webpack": "^2.5.1", diff --git a/yarn.lock b/yarn.lock index 71da80c1a..d3317f59c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6510,6 +6510,10 @@ tiny-emitter@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-1.0.2.tgz#8e49470d3f55f89e247210368a6bb9fb51aa1601" +tiny-queue@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/tiny-queue/-/tiny-queue-0.2.1.tgz#25a67f2c6e253b2ca941977b5ef7442ef97a6046" + to-arraybuffer@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43"