Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[2.x] Use set and clear debouncer upon completion. Fixes #5250 #5500

Merged
merged 8 commits into from
Mar 20, 2019
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 49 additions & 2 deletions lib/utils/debounce.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
this._timer = this._asyncModule.run(() => {
this._timer = null;
this._callback();
debouncerQueue.delete(this);
});
}
/**
Expand All @@ -49,10 +50,23 @@
*/
cancel() {
if (this.isActive()) {
this._asyncModule.cancel(this._timer);
this._cancelAsync();
this._timer = null;
// 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() {
this._asyncModule.cancel(/** @type {number} */(this._timer));
}
/**
* Flushes an active debouncer and returns a reference to itself.
*
Expand Down Expand Up @@ -104,7 +118,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();
}
Expand All @@ -115,5 +131,36 @@

/** @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;
});
}
});
debouncerQueue = new Set();
return didFlush;
};

})();
</script>
30 changes: 2 additions & 28 deletions lib/utils/flush.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,37 +8,11 @@
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<link rel="import" href="boot.html">
<link rel="import" href="debounce.html">
<script>
(function() {
'use strict';

let debouncerQueue = [];

/**
* Adds a `Polymer.Debouncer` to a list of globally flushable tasks.
*
* @memberof Polymer
* @param {!Polymer.Debouncer} debouncer Debouncer to enqueue
* @return {void}
*/
Polymer.enqueueDebouncer = function(debouncer) {
debouncerQueue.push(debouncer);
};

function flushDebouncers() {
const didFlush = Boolean(debouncerQueue.length);
while (debouncerQueue.length) {
try {
debouncerQueue.shift().flush();
} catch(e) {
setTimeout(() => {
throw e;
});
}
}
return didFlush;
}

/**
* Forces several classes of asynchronously queued tasks to flush:
* - Debouncers added via `enqueueDebouncer`
Expand All @@ -54,7 +28,7 @@
if (window.ShadyCSS && window.ShadyCSS.ScopingShim) {
window.ShadyCSS.ScopingShim.flush();
}
debouncers = flushDebouncers();
debouncers = Polymer.flushDebouncers();
} while (shadyDOM || debouncers);
};

Expand Down
38 changes: 38 additions & 0 deletions test/unit/debounce.html
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,44 @@

});
});

suite('enqueueDebouncer & flush', function() {

const testEnqueue = (shouldFlush, done) => {
const actualOrder = [];
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) {
Polymer.flush();
assert.deepEqual(actualOrder, [db1.cb, db2.cb, db3.cb, db4.cb]);
done();
} else {
Polymer.Async.timeOut.run(() => {
assert.deepEqual(actualOrder, [db4.cb, db2.cb, db1.cb, db3.cb]);
done();
});
}
};

test('non-flushed', function(done) {
testEnqueue(false, done);
});

test('flushed', function(done) {
testEnqueue(true, done);
});

});
</script>
</body>
</html>
11 changes: 11 additions & 0 deletions types/lib/utils/debounce.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand All @@ -80,4 +85,10 @@ declare namespace Polymer {
*/
isActive(): boolean;
}


/**
* Adds a `Debouncer` to a list of globally flushable tasks.
*/
function enqueueDebouncer(debouncer: Debouncer): void;
}
7 changes: 1 addition & 6 deletions types/lib/utils/flush.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,11 @@
// tslint:disable:variable-name Describing an API that's defined elsewhere.

/// <reference path="boot.d.ts" />
/// <reference path="debounce.d.ts" />

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`
Expand Down