diff --git a/lib/utils/debounce.html b/lib/utils/debounce.html index 1507faa20a..5290285e3b 100644 --- a/lib/utils/debounce.html +++ b/lib/utils/debounce.html @@ -39,6 +39,7 @@ this._callback = callback; this._timer = this._asyncModule.run(() => { this._timer = null; + debouncerQueue.delete(this); this._callback(); }); } @@ -49,7 +50,22 @@ */ cancel() { if (this.isActive()) { - this._asyncModule.cancel(this._timer); + this._cancelAsync(); + // Canceling a debouncer removes its spot from the flush queue, + // so if a debouncer is manually canceled and re-debounced, it + // will reset its flush order (this is a very minor difference from 1.x) + // Re-debouncing via the `debounce` API retains the 1.x FIFO flush order + debouncerQueue.delete(this); + } + } + /** + * Cancels a debouncer's async callback. + * + * @return {void} + */ + _cancelAsync() { + if (this.isActive()) { + this._asyncModule.cancel(/** @type {number} */(this._timer)); this._timer = null; } } @@ -104,7 +120,9 @@ */ static debounce(debouncer, asyncModule, callback) { if (debouncer instanceof Debouncer) { - debouncer.cancel(); + // Cancel the async callback, but leave in debouncerQueue if it was + // enqueued, to maintain 1.x flush order + debouncer._cancelAsync(); } else { debouncer = new Debouncer(); } @@ -115,5 +133,35 @@ /** @const */ Polymer.Debouncer = Debouncer; + + let debouncerQueue = new Set(); + + /** + * Adds a `Debouncer` to a list of globally flushable tasks. + * + * @memberof Polymer + * @param {!Debouncer} debouncer Debouncer to enqueue + * @return {void} + */ + Polymer.enqueueDebouncer = function(debouncer) { + debouncerQueue.add(debouncer); + }; + + Polymer.flushDebouncers = function() { + const didFlush = Boolean(debouncerQueue.size); + // If new debouncers are added while flushing, Set.forEach will ensure + // newly added ones are also flushed + debouncerQueue.forEach(debouncer => { + try { + debouncer.flush(); + } catch(e) { + setTimeout(() => { + throw e; + }); + } + }); + return didFlush; + }; + })(); diff --git a/lib/utils/flush.html b/lib/utils/flush.html index 3feaad6166..0ab98780cd 100644 --- a/lib/utils/flush.html +++ b/lib/utils/flush.html @@ -8,37 +8,11 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt --> + diff --git a/types/lib/utils/debounce.d.ts b/types/lib/utils/debounce.d.ts index 3800afc4a2..57bf1846ac 100644 --- a/types/lib/utils/debounce.d.ts +++ b/types/lib/utils/debounce.d.ts @@ -68,6 +68,11 @@ declare namespace Polymer { */ cancel(): void; + /** + * Cancels a debouncer's async callback. + */ + _cancelAsync(): void; + /** * Flushes an active debouncer and returns a reference to itself. */ @@ -80,4 +85,10 @@ declare namespace Polymer { */ isActive(): boolean; } + + + /** + * Adds a `Debouncer` to a list of globally flushable tasks. + */ + function enqueueDebouncer(debouncer: Debouncer): void; } diff --git a/types/lib/utils/flush.d.ts b/types/lib/utils/flush.d.ts index fde1037a6f..6360fcd8b6 100644 --- a/types/lib/utils/flush.d.ts +++ b/types/lib/utils/flush.d.ts @@ -12,16 +12,11 @@ // tslint:disable:variable-name Describing an API that's defined elsewhere. /// +/// declare namespace Polymer { - /** - * Adds a `Polymer.Debouncer` to a list of globally flushable tasks. - */ - function enqueueDebouncer(debouncer: Polymer.Debouncer): void; - - /** * Forces several classes of asynchronously queued tasks to flush: * - Debouncers added via `enqueueDebouncer`