Commit 52e9d965 authored by fukino@chromium.org's avatar fukino@chromium.org

Modify AsyncUtil.Aggregation to be able to keep calling in limited rate.

I changed behavior of AsyncUtil.Aggregation and changed its name to AsyncUtil.RateLimiter.
Previously, AsyncUtil.Aggregation aggregates consecutive calls as much as possible.
To keep update the UI, from now the closure will be called as much as possible keeping given minimum interval.

BUG=373627
TEST=manually change the window size continuously.

Review URL: https://codereview.chromium.org/329083002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@276703 0039d316-1c4b-4281-b951-d872f2087c98
parent 82bc1ece
...@@ -255,65 +255,72 @@ AsyncUtil.Group.prototype.finish_ = function(task) { ...@@ -255,65 +255,72 @@ AsyncUtil.Group.prototype.finish_ = function(task) {
}; };
/** /**
* Aggregates consecutive calls and executes the closure only once instead of * Samples calls so that they are not called too frequently.
* several times. The first call is always called immediately, and the next * The first call is always called immediately, and the following calls may
* consecutive ones are aggregated and the closure is called only once once * be skipped or delayed to keep each interval no less than |minInterval_|.
* |delay| amount of time passes after the last call to run().
* *
* @param {function()} closure Closure to be aggregated. * @param {function()} closure Closure to be called.
* @param {number=} opt_delay Minimum aggregation time in milliseconds. Default * @param {number=} opt_minInterval Minimum interval between each call in
* is 50 milliseconds. * milliseconds. Default is 200 milliseconds.
* @constructor * @constructor
*/ */
AsyncUtil.Aggregation = function(closure, opt_delay) { AsyncUtil.RateLimiter = function(closure, opt_minInterval) {
/** /**
* @type {number} * @type {function()}
* @private * @private
*/ */
this.delay_ = opt_delay || 50; this.closure_ = closure;
/** /**
* @type {function()} * @type {number}
* @private * @private
*/ */
this.closure_ = closure; this.minInterval_ = opt_minInterval || 200;
/** /**
* @type {number?} * @type {number}
* @private * @private
*/ */
this.scheduledRunsTimer_ = null; this.scheduledRunsTimer_ = 0;
/** /**
* This variable remembers the last time the closure is called.
* @type {number} * @type {number}
* @private * @private
*/ */
this.lastRunTime_ = 0; this.lastRunTime_ = 0;
Object.seal(this);
}; };
/** /**
* Runs a closure. Skips consecutive calls. The first call is called * Requests to run the closure.
* immediately. * Skips or delays calls so that the intervals between calls are no less than
* |minInteval_| milliseconds.
*/ */
AsyncUtil.Aggregation.prototype.run = function() { AsyncUtil.RateLimiter.prototype.run = function() {
// If recently called, then schedule the consecutive call with a delay. var now = Date.now();
if (Date.now() - this.lastRunTime_ < this.delay_) { // If |minInterval| has not passed since the closure is run, skips or delays
this.cancelScheduledRuns_(); // this run.
this.scheduledRunsTimer_ = setTimeout(this.runImmediately_.bind(this), if (now - this.lastRunTime_ < this.minInterval_) {
this.delay_ + 1); // Delays this run only when there is no scheduled run.
this.lastRunTime_ = Date.now(); // Otherwise, simply skip this run.
if (!this.scheduledRunsTimer_) {
this.scheduledRunsTimer_ = setTimeout(
this.runImmediately.bind(this),
this.lastRunTime_ + this.minInterval_ - now);
}
return; return;
} }
// Otherwise, run immediately. // Otherwise, run immediately
this.runImmediately_(); this.runImmediately();
}; };
/** /**
* Calls the schedule immediately and cancels any scheduled calls. * Calls the scheduled run immediately and cancels any scheduled calls.
* @private
*/ */
AsyncUtil.Aggregation.prototype.runImmediately_ = function() { AsyncUtil.RateLimiter.prototype.runImmediately = function() {
this.cancelScheduledRuns_(); this.cancelScheduledRuns_();
this.closure_(); this.closure_();
this.lastRunTime_ = Date.now(); this.lastRunTime_ = Date.now();
...@@ -323,9 +330,9 @@ AsyncUtil.Aggregation.prototype.runImmediately_ = function() { ...@@ -323,9 +330,9 @@ AsyncUtil.Aggregation.prototype.runImmediately_ = function() {
* Cancels all scheduled runs (if any). * Cancels all scheduled runs (if any).
* @private * @private
*/ */
AsyncUtil.Aggregation.prototype.cancelScheduledRuns_ = function() { AsyncUtil.RateLimiter.prototype.cancelScheduledRuns_ = function() {
if (this.scheduledRunsTimer_) { if (this.scheduledRunsTimer_) {
clearTimeout(this.scheduledRunsTimer_); clearTimeout(this.scheduledRunsTimer_);
this.scheduledRunsTimer_ = null; this.scheduledRunsTimer_ = 0;
} }
}; };
...@@ -53,8 +53,8 @@ FileGrid.decorate = function(self, metadataCache, volumeManager) { ...@@ -53,8 +53,8 @@ FileGrid.decorate = function(self, metadataCache, volumeManager) {
return item; return item;
}; };
self.relayoutAggregation_ = self.relayoutRateLimiter_ =
new AsyncUtil.Aggregation(self.relayoutImmediately_.bind(self)); new AsyncUtil.RateLimiter(self.relayoutImmediately_.bind(self));
}; };
/** /**
...@@ -83,7 +83,7 @@ FileGrid.prototype.updateListItemsMetadata = function(type, props) { ...@@ -83,7 +83,7 @@ FileGrid.prototype.updateListItemsMetadata = function(type, props) {
* Redraws the UI. Skips multiple consecutive calls. * Redraws the UI. Skips multiple consecutive calls.
*/ */
FileGrid.prototype.relayout = function() { FileGrid.prototype.relayout = function() {
this.relayoutAggregation_.run(); this.relayoutRateLimiter_.run();
}; };
/** /**
......
...@@ -305,8 +305,8 @@ FileTable.decorate = function(self, metadataCache, fullPage) { ...@@ -305,8 +305,8 @@ FileTable.decorate = function(self, metadataCache, fullPage) {
e.preventDefault(); e.preventDefault();
}); });
self.relayoutAggregation_ = self.relayoutRateLimiter_ =
new AsyncUtil.Aggregation(self.relayoutImmediately_.bind(self)); new AsyncUtil.RateLimiter(self.relayoutImmediately_.bind(self));
// Override header#redraw to use FileTableSplitter. // Override header#redraw to use FileTableSplitter.
self.header_.redraw = function() { self.header_.redraw = function() {
...@@ -734,7 +734,7 @@ FileTable.prototype.setBottomMarginForPanel = function(margin) { ...@@ -734,7 +734,7 @@ FileTable.prototype.setBottomMarginForPanel = function(margin) {
* Redraws the UI. Skips multiple consecutive calls. * Redraws the UI. Skips multiple consecutive calls.
*/ */
FileTable.prototype.relayout = function() { FileTable.prototype.relayout = function() {
this.relayoutAggregation_.run(); this.relayoutRateLimiter_.run();
}; };
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment