about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNolan Lawson <nolan@nolanlawson.com>2017-05-31 06:11:33 -0700
committerEugen Rochko <eugen@zeonfederated.com>2017-05-31 15:11:33 +0200
commit0e12a8dab9ccec83b91722a8b0a065c0919af98a (patch)
treeb8207645cca8285f845e0fac381581a14a56c8ed
parent3652a39de0d40acad1f2b170c74338b4fda01359 (diff)
Improve scheduling of requestIdleCallback tasks (#3477)
-rw-r--r--app/javascript/mastodon/components/status.js3
-rw-r--r--app/javascript/mastodon/features/ui/util/schedule_idle_task.js29
-rw-r--r--package.json1
-rw-r--r--yarn.lock4
4 files changed, 36 insertions, 1 deletions
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"