diff --git a/src/prepare/BasePrepare.js b/src/prepare/BasePrepare.js index 125d4e1..bdfcdc5 100644 --- a/src/prepare/BasePrepare.js +++ b/src/prepare/BasePrepare.js @@ -75,6 +75,21 @@ * @private */ this.ticking = false; + + /** + * 'bound' call for prepareItems(). + * @type {Function} + * @private + */ + this.delayedTick = () => + { + // unlikely, but in case we were destroyed between tick() and delayedTick() + if (!this.queue) + { + return; + } + this.prepareItems(); + }; } /** @@ -111,7 +126,7 @@ if (!this.ticking) { this.ticking = true; - SharedTicker.add(this.tick, this); + SharedTicker.addOnce(this.tick, this); } } else if (done) @@ -127,6 +142,17 @@ */ tick() { + setTimeout(this.delayedTick, 0); + } + + /** + * Actually prepare items. This is handled outside of the tick because it will take a while + * and we do NOT want to block the current animation frame from rendering. + * + * @private + */ + prepareItems() + { this.limiter.beginFrame(); // Upload the graphics while (this.queue.length && this.limiter.allowedToUpload()) @@ -155,8 +181,6 @@ { this.ticking = false; - SharedTicker.remove(this.tick, this); - const completes = this.completes.slice(0); this.completes.length = 0; @@ -166,6 +190,11 @@ completes[i](); } } + else + { + // if we are not finished, on the next rAF do this again + SharedTicker.addOnce(this.tick, this); + } } /** diff --git a/src/prepare/BasePrepare.js b/src/prepare/BasePrepare.js index 125d4e1..bdfcdc5 100644 --- a/src/prepare/BasePrepare.js +++ b/src/prepare/BasePrepare.js @@ -75,6 +75,21 @@ * @private */ this.ticking = false; + + /** + * 'bound' call for prepareItems(). + * @type {Function} + * @private + */ + this.delayedTick = () => + { + // unlikely, but in case we were destroyed between tick() and delayedTick() + if (!this.queue) + { + return; + } + this.prepareItems(); + }; } /** @@ -111,7 +126,7 @@ if (!this.ticking) { this.ticking = true; - SharedTicker.add(this.tick, this); + SharedTicker.addOnce(this.tick, this); } } else if (done) @@ -127,6 +142,17 @@ */ tick() { + setTimeout(this.delayedTick, 0); + } + + /** + * Actually prepare items. This is handled outside of the tick because it will take a while + * and we do NOT want to block the current animation frame from rendering. + * + * @private + */ + prepareItems() + { this.limiter.beginFrame(); // Upload the graphics while (this.queue.length && this.limiter.allowedToUpload()) @@ -155,8 +181,6 @@ { this.ticking = false; - SharedTicker.remove(this.tick, this); - const completes = this.completes.slice(0); this.completes.length = 0; @@ -166,6 +190,11 @@ completes[i](); } } + else + { + // if we are not finished, on the next rAF do this again + SharedTicker.addOnce(this.tick, this); + } } /** diff --git a/test/prepare/BasePrepare.js b/test/prepare/BasePrepare.js index a0fa06b..769ce4e 100644 --- a/test/prepare/BasePrepare.js +++ b/test/prepare/BasePrepare.js @@ -63,7 +63,7 @@ expect(prep.queue).to.contain(uploadItem); - prep.tick(); + prep.prepareItems(); expect(addHook.calledOnce).to.be.true; expect(uploadHook.calledOnce).to.be.true; @@ -111,7 +111,7 @@ expect(prep.queue).to.have.lengthOf(1); - prep.tick(); + prep.prepareItems(); expect(prep.queue).to.be.empty; expect(addHook.calledOnce).to.be.true;