Bug 852531 - [New Tab Page] use promises to wait for a batch of operations to complete; r=yoric

This commit is contained in:
Tim Taubert 2013-03-20 17:06:34 +01:00
parent 66f8ab574d
commit bb9a0e6b4e
4 changed files with 22 additions and 98 deletions

View File

@ -1,76 +0,0 @@
#ifdef 0
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#endif
/**
* This class makes it easy to wait until a batch of callbacks has finished.
*
* Example:
*
* let batch = new Batch(function () alert("finished"));
* let pop = batch.pop.bind(batch);
*
* for (let i = 0; i < 5; i++) {
* batch.push();
* setTimeout(pop, i * 1000);
* }
*
* batch.close();
*/
function Batch(aCallback) {
this._callback = aCallback;
}
Batch.prototype = {
/**
* The number of batch entries.
*/
_count: 0,
/**
* Whether this batch is closed.
*/
_closed: false,
/**
* Increases the number of batch entries by one.
*/
push: function Batch_push() {
if (!this._closed)
this._count++;
},
/**
* Decreases the number of batch entries by one.
*/
pop: function Batch_pop() {
if (this._count)
this._count--;
if (this._closed)
this._check();
},
/**
* Closes the batch so that no new entries can be added.
*/
close: function Batch_close() {
if (this._closed)
return;
this._closed = true;
this._check();
},
/**
* Checks if the batch has finished.
*/
_check: function Batch_check() {
if (this._count == 0 && this._callback) {
this._callback();
this._callback = null;
}
}
};

View File

@ -11,6 +11,7 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/PageThumbs.jsm");
Cu.import("resource://gre/modules/NewTabUtils.jsm");
Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js");
XPCOMUtils.defineLazyModuleGetter(this, "Rect",
"resource://gre/modules/Geometry.jsm");
@ -39,7 +40,6 @@ function inPrivateBrowsingMode() {
const HTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
#include batch.js
#include transformations.js
#include page.js
#include grid.js

View File

@ -169,37 +169,33 @@ let gTransformation = {
* callback - the callback to call when finished
*/
rearrangeSites: function Transformation_rearrangeSites(aSites, aOptions) {
let batch;
let batch = [];
let cells = gGrid.cells;
let callback = aOptions && aOptions.callback;
let unfreeze = aOptions && aOptions.unfreeze;
if (callback) {
batch = new Batch(callback);
callback = function () batch.pop();
}
aSites.forEach(function (aSite, aIndex) {
// Do not re-arrange empty cells or the dragged site.
if (!aSite || aSite == gDrag.draggedSite)
return;
if (batch)
batch.push();
let deferred = Promise.defer();
batch.push(deferred.promise);
let cb = function () deferred.resolve();
if (!cells[aIndex])
// The site disappeared from the grid, hide it.
this.hideSite(aSite, callback);
this.hideSite(aSite, cb);
else if (this._getNodeOpacity(aSite.node) != 1)
// The site disappeared before but is now back, show it.
this.showSite(aSite, callback);
this.showSite(aSite, cb);
else
// The site's position has changed, move it around.
this._moveSite(aSite, aIndex, {unfreeze: unfreeze, callback: callback});
this._moveSite(aSite, aIndex, {unfreeze: unfreeze, callback: cb});
}, this);
if (batch)
batch.close();
let wait = Promise.promised(function () callback && callback());
wait.apply(null, batch);
},
/**

View File

@ -126,7 +126,7 @@ let gUpdater = {
* @param aCallback The callback to call when finished.
*/
_removeLegacySites: function Updater_removeLegacySites(aSites, aCallback) {
let batch = new Batch(aCallback);
let batch = [];
// Delete sites that were removed from the grid.
gGrid.sites.forEach(function (aSite) {
@ -134,7 +134,8 @@ let gUpdater = {
if (!aSite || aSites.indexOf(aSite) != -1)
return;
batch.push();
let deferred = Promise.defer();
batch.push(deferred.promise);
// Fade out the to-be-removed site.
gTransformation.hideSite(aSite, function () {
@ -142,11 +143,12 @@ let gUpdater = {
// Remove the site from the DOM.
node.parentNode.removeChild(node);
batch.pop();
deferred.resolve();
});
});
batch.close();
let wait = Promise.promised(aCallback);
wait.apply(null, batch);
},
/**
@ -156,14 +158,15 @@ let gUpdater = {
*/
_fillEmptyCells: function Updater_fillEmptyCells(aLinks, aCallback) {
let {cells, sites} = gGrid;
let batch = new Batch(aCallback);
let batch = [];
// Find empty cells and fill them.
sites.forEach(function (aSite, aIndex) {
if (aSite || !aLinks[aIndex])
return;
batch.push();
let deferred = Promise.defer();
batch.push(deferred.promise);
// Create the new site and fade it in.
let site = gGrid.createSite(aLinks[aIndex], cells[aIndex]);
@ -174,9 +177,10 @@ let gUpdater = {
// Flush all style changes for the dynamically inserted site to make
// the fade-in transition work.
window.getComputedStyle(site.node).opacity;
gTransformation.showSite(site, function () batch.pop());
gTransformation.showSite(site, function () deferred.resolve());
});
batch.close();
let wait = Promise.promised(aCallback);
wait.apply(null, batch);
}
};