Skip to content

Commit

Permalink
[Enhancement]: improve idle case with improved scrollTo under high lo…
Browse files Browse the repository at this point in the history
…ads (#269)

* [Enhancement]: improve idle case with improved scrollTo under high loads

* add param for Element
  • Loading branch information
snewcomer authored Dec 24, 2020
1 parent 19a8720 commit 1190291
Showing 1 changed file with 20 additions and 61 deletions.
81 changes: 20 additions & 61 deletions addon/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,50 +10,6 @@ const MAX_ATTEMPTS = 100; // rAF runs every 16ms ideally, so 60x a second

let requestId;
let callbackRequestId;
let idleRequestId;

class CounterPool {
constructor() {
this._counter = 0;
this.onFinishedPromise = null;
this.onFinishedCallback = null;

this.flush();
}

get counter() {
return this._counter;
}
set counter(value) {
// put a cap so flush queue doesn't take too many paint cycles
this._counter = Math.min(value, 2);
}

flush() {
if (this.counter === 0 && this.onFinishedPromise && this.onFinishedPromise.then) {
// when we are done, attach a then callback and update scroll position
this.onFinishedPromise.then(() => {
this.onFinishedCallback && this.onFinishedCallback();
});
}

idleRequestId = window.requestAnimationFrame(() => {
this.decrement();
this.flush();
});
}

decrement() {
this.counter = this.counter - 1;
}

destroy() {
window.cancelAnimationFrame(idleRequestId);
this.counter = 0;
this.onFinishedPromise = null;
this.onFinishedCallback = null;
}
}

/**
* By default, we start checking to see if the document height is >= the last known `y` position
Expand All @@ -63,14 +19,20 @@ class CounterPool {
* @method tryScrollRecursively
* @param {Function} fn
* @param {Object} scrollHash
* @param {Element} [element]
* @void
*/
function tryScrollRecursively(fn, scrollHash) {
const body = document.body;
const html = document.documentElement;
function tryScrollRecursively(fn, scrollHash, element) {
let documentHeight;
// read DOM outside of rAF
const documentHeight = Math.max(body.scrollHeight, body.offsetHeight,
html.clientHeight, html.scrollHeight, html.offsetHeight);
if (element) {
documentHeight = Math.max(element.scrollHeight, element.offsetHeight, element.clientHeight);
} else {
const body = document.body;
const html = document.documentElement;
documentHeight = Math.max(body.scrollHeight, body.offsetHeight,
html.clientHeight, html.scrollHeight, html.offsetHeight);
}

callbackRequestId = window.requestAnimationFrame(() => {
// write DOM (scrollTo causes reflow)
Expand Down Expand Up @@ -172,8 +134,11 @@ class EmberRouterScroll extends EmberRouter {
const element = document.getElementById(scrollElement.substring(1));

if (element) {
element.scrollLeft = scrollPosition.x;
element.scrollTop = scrollPosition.y;
let fn = (x, y) => {
element.scrollLeft = x;
element.scrollTop = y;
}
tryScrollRecursively(fn, scrollPosition, element);
}
}
}
Expand Down Expand Up @@ -201,18 +166,12 @@ class EmberRouterScroll extends EmberRouter {
// out of the option, this happens on the tightest schedule
scheduleOnce('render', this, CALLBACK, transition);
} else if (scrollWhenAfterRender && !scrollWhenIdle) {
// out of the option, this happens on the tightest schedule
// out of the option, this happens on the second tightest schedule
scheduleOnce('afterRender', this, CALLBACK, transition);
} else {
if (!this.idlePool) {
this.idlePool = new CounterPool();
}

// increments happen all in one batch (before processing flush queue) and happens indeterminately
// e.g. 4, 6, 10 times this could be called
this.idlePool.counter = this.idlePool.counter + 1;
this.idlePool.onFinishedPromise = whenRouteIdle();
this.idlePool.onFinishedCallback = this.updateScrollPosition.bind(this, transition);
whenRouteIdle().then(() => {
this.updateScrollPosition(transition);
});
}
}
}
Expand Down

0 comments on commit 1190291

Please sign in to comment.