diff --git a/lib/utils/debounce.html b/lib/utils/debounce.html
index 54fc859623..01142cbd95 100644
--- a/lib/utils/debounce.html
+++ b/lib/utils/debounce.html
@@ -50,10 +50,19 @@
*/
cancel() {
if (this.isActive()) {
- this._asyncModule.cancel(this._timer);
+ this._cancelAsync();
this._timer = null;
+ debouncerQueue.delete(this);
}
}
+ /**
+ * Cancels a debouncer's async callback.
+ *
+ * @return {void}
+ */
+ _cancelAsync() {
+ this._asyncModule.cancel(/** @type {number} */(this._timer));
+ }
/**
* Flushes an active debouncer and returns a reference to itself.
*
@@ -105,7 +114,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();
}
@@ -127,11 +138,6 @@
* @return {void}
*/
Polymer.enqueueDebouncer = function(debouncer) {
- // Re-enqueued debouncers are put at the end of the queue; for Set, this
- // means removing and re-adding, since forEach traverses insertion order
- if (debouncerQueue.has(debouncer)) {
- debouncerQueue.delete(debouncer);
- }
debouncerQueue.add(debouncer);
};
diff --git a/test/unit/debounce.html b/test/unit/debounce.html
index f2fbc81935..fbb330753c 100644
--- a/test/unit/debounce.html
+++ b/test/unit/debounce.html
@@ -211,47 +211,33 @@
});
suite('enqueueDebouncer & flush', function() {
- function testEnqueue(shouldFlush, done) {
- // Longer-running debouncer
- const timeoutCallback = sinon.spy(() => actualCallbacks.push(timeoutCallback));
- Polymer.enqueueDebouncer(Polymer.Debouncer.debounce(null, Polymer.Async.timeOut, timeoutCallback));
- // Set of short-running debouncers enqueued in the middle of first set
- const nestedCallbacks = [];
- for (let i=0; i<150; i++) {
- nestedCallbacks.push(sinon.spy(() =>
- actualCallbacks.push(nestedCallbacks[i])));
- }
- // First set of short-running debouncers
- const microtaskCallbacks = [];
- for (let i=0; i<150; i++) {
- microtaskCallbacks.push(sinon.spy(() => {
- actualCallbacks.push(microtaskCallbacks[i]);
- if (i === 125) {
- nestedCallbacks.forEach(cb =>
- Polymer.enqueueDebouncer(Polymer.Debouncer.debounce(null, Polymer.Async.microTask, cb)));
- }
- }));
- }
- microtaskCallbacks.forEach(cb =>
- Polymer.enqueueDebouncer(Polymer.Debouncer.debounce(null, Polymer.Async.microTask, cb)));
- // Expect short before long
- let expectedCallbacks;
- const actualCallbacks = [];
- const verify = () => {
- actualCallbacks.forEach(cb => assert.isTrue(cb.calledOnce));
- assert.deepEqual(expectedCallbacks, actualCallbacks);
- done();
+
+ const testEnqueue = (shouldFlush, done) => {
+ const actualOrder = [];
+ let i=1;
+ const enqueue = (type, {db, cb} = {}) => {
+ cb = cb || (() => actualOrder.push(cb));
+ db = Polymer.Debouncer.debounce(db, type, cb);
+ Polymer.enqueueDebouncer(db);
+ return {db, cb};
};
+ const db1 = enqueue(Polymer.Async.microTask);
+ const db2 = enqueue(Polymer.Async.microTask);
+ const db3 = enqueue(Polymer.Async.timeOut);
+ const db4 = enqueue(Polymer.Async.microTask);
+ enqueue(Polymer.Async.microTask, db2);
+ enqueue(Polymer.Async.microTask, db1);
if (shouldFlush) {
- expectedCallbacks = [timeoutCallback, ...microtaskCallbacks, ...nestedCallbacks];
Polymer.flush();
- // When flushing, order is order of enqueing
- verify();
+ assert.deepEqual(actualOrder, [db1.cb, db2.cb, db3.cb, db4.cb]);
+ done();
} else {
- expectedCallbacks = [...microtaskCallbacks, ...nestedCallbacks, timeoutCallback];
- Polymer.Async.timeOut.run(verify);
+ Polymer.Async.timeOut.run(() => {
+ assert.deepEqual(actualOrder, [db4.cb, db2.cb, db1.cb, db3.cb]);
+ done();
+ });
}
- }
+ };
test('non-flushed', function(done) {
testEnqueue(false, done);