Defer intersection monitoring until needed to prevent race conditions (#7278)

* defer visibility rendering until actually used to prevent race conditions

* remove extrace space
This commit is contained in:
Scott Bell 2023-12-15 09:40:36 +01:00 committed by GitHub
parent 4075a31d96
commit 2675220452
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 14 additions and 3 deletions

2
API.md
View File

@ -1319,6 +1319,8 @@ The `renderWhenVisible` function is passed to the show function as part of the `
Additionally, `renderWhenVisible` returns a boolean value indicating whether the provided function was executed immediately (`true`) or deferred (`false`). Additionally, `renderWhenVisible` returns a boolean value indicating whether the provided function was executed immediately (`true`) or deferred (`false`).
Monitoring of visibility begins after the first call to `renderWhenVisible` is made.
Heres the signature for the show function: Heres the signature for the show function:
`show(element, isEditing, viewOptions)` `show(element, isEditing, viewOptions)`

View File

@ -199,8 +199,8 @@ export default {
mounted() { mounted() {
this.chartVisible = true; this.chartVisible = true;
this.chartContainer = this.$refs.chart; this.chartContainer = this.$refs.chart;
this.drawnOnce = false;
this.visibilityObserver = new IntersectionObserver(this.visibilityChanged); this.visibilityObserver = new IntersectionObserver(this.visibilityChanged);
this.visibilityObserver.observe(this.chartContainer);
eventHelpers.extend(this); eventHelpers.extend(this);
this.seriesModels = []; this.seriesModels = [];
this.config = this.getConfig(); this.config = this.getConfig();
@ -687,6 +687,10 @@ export default {
if (!this.drawScheduled) { if (!this.drawScheduled) {
const called = this.renderWhenVisible(this.draw); const called = this.renderWhenVisible(this.draw);
this.drawScheduled = called; this.drawScheduled = called;
if (!this.drawnOnce && called) {
this.drawnOnce = true;
this.visibilityObserver.observe(this.chartContainer);
}
} }
}, },
draw() { draw() {

View File

@ -40,9 +40,9 @@ export default class VisibilityObserver {
} }
this.#element = element; this.#element = element;
this.isIntersecting = true; this.isIntersecting = true;
this.calledOnce = false;
this.#observer = new IntersectionObserver(this.#observerCallback); this.#observer = new IntersectionObserver(this.#observerCallback);
this.#observer.observe(this.#element);
this.lastUnfiredFunc = null; this.lastUnfiredFunc = null;
this.renderWhenVisible = this.renderWhenVisible.bind(this); this.renderWhenVisible = this.renderWhenVisible.bind(this);
} }
@ -66,7 +66,12 @@ export default class VisibilityObserver {
* @returns {boolean} True if the function was executed immediately, false otherwise. * @returns {boolean} True if the function was executed immediately, false otherwise.
*/ */
renderWhenVisible(func) { renderWhenVisible(func) {
if (this.isIntersecting) { if (!this.calledOnce) {
this.calledOnce = true;
this.#observer.observe(this.#element);
window.requestAnimationFrame(func);
return true;
} else if (this.isIntersecting) {
window.requestAnimationFrame(func); window.requestAnimationFrame(func);
return true; return true;
} else { } else {