diff options
author | kelvinp@chromium.org <kelvinp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-08-19 02:32:52 +0000 |
---|---|---|
committer | kelvinp@chromium.org <kelvinp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-08-19 02:34:30 +0000 |
commit | d8391a54250b7c63bcfe410b646bcfa308b519d8 (patch) | |
tree | de6508e0e8b53165d0cbc8e775a25301ac95d3ab /remoting | |
parent | f539115f00327c512e447ba5167a88c26ff4e562 (diff) | |
download | chromium_src-d8391a54250b7c63bcfe410b646bcfa308b519d8.zip chromium_src-d8391a54250b7c63bcfe410b646bcfa308b519d8.tar.gz chromium_src-d8391a54250b7c63bcfe410b646bcfa308b519d8.tar.bz2 |
Base.deferred
Promise is a great tool for writing asynchronous code. However, the construct
var p = new promise(function init(resolve, reject) {
... // code that fulfills the promise.
});
forces the promise resolving logic to reside in the init function
of the constructor. This is problematic when you need to resolve the
promise in a member function (which is quite common for event callbacks).
base.Deferred comes to the rescue. It encapsulates a promise
object and exposes member methods (resolve/reject) to fulfill it.
Here are the recommended steps to follow when implementing an asynchronous
function that returns a promise:
1. Create a deferred object by calling
var deferred = new base.Deferred();
2. Call deferred.resolve() when the asynchronous operation finishes.
3. Call deferred.reject() when the asynchronous operation fails.
4. Returns deferred.promise() to the caller so that it can subscribe
to status changes using the |then| handler.
Sample Usage:
function myAsyncAPI() {
var deferred = new base.Deferred();
window.setTimeout(function() {
deferred.resolve();
}, 100);
return deferred.promise();
};
Review URL: https://codereview.chromium.org/483753004
Cr-Commit-Position: refs/heads/master@{#290460}
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@290460 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting')
-rw-r--r-- | remoting/webapp/base.js | 77 | ||||
-rw-r--r-- | remoting/webapp/unittests/base_unittest.js | 32 |
2 files changed, 109 insertions, 0 deletions
diff --git a/remoting/webapp/base.js b/remoting/webapp/base.js index 54f1984..c2bf1a2 100644 --- a/remoting/webapp/base.js +++ b/remoting/webapp/base.js @@ -149,6 +149,83 @@ base.urlJoin = function(url, opt_params) { return url + '?' + queryParameters.join('&'); }; +/** + * Promise is a great tool for writing asynchronous code. However, the construct + * var p = new promise(function init(resolve, reject) { + * ... // code that fulfills the Promise. + * }); + * forces the Promise-resolving logic to reside in the |init| function + * of the constructor. This is problematic when you need to resolve the + * Promise in a member function(which is quite common for event callbacks). + * + * base.Deferred comes to the rescue. It encapsulates a Promise + * object and exposes member methods (resolve/reject) to fulfill it. + * + * Here are the recommended steps to follow when implementing an asynchronous + * function that returns a Promise: + * 1. Create a deferred object by calling + * var deferred = new base.Deferred(); + * 2. Call deferred.resolve() when the asynchronous operation finishes. + * 3. Call deferred.reject() when the asynchronous operation fails. + * 4. Return deferred.promise() to the caller so that it can subscribe + * to status changes using the |then| handler. + * + * Sample Usage: + * function myAsyncAPI() { + * var deferred = new base.Deferred(); + * window.setTimeout(function() { + * deferred.resolve(); + * }, 100); + * return deferred.promise(); + * }; + * + * @constructor + */ +base.Deferred = function() { + /** + * @type {?function(?=)} + * @private + */ + this.resolve_ = null; + + /** + * @type {?function(?)} + * @private + */ + this.reject_ = null; + + /** + * @type {Promise} + * @private + */ + this.promise_ = new Promise( + /** + * @param {function(?=):void} resolve + * @param {function(?):void} reject + * @this {base.Deferred} + */ + function(resolve, reject) { + this.resolve_ = resolve; + this.reject_ = reject; + }.bind(this) + ); +}; + +/** @param {*} reason */ +base.Deferred.prototype.reject = function(reason) { + this.reject_(reason); +}; + +/** @param {*=} opt_value */ +base.Deferred.prototype.resolve = function(opt_value) { + this.resolve_(opt_value); +}; + +/** @return {Promise} */ +base.Deferred.prototype.promise = function() { + return this.promise_; +}; + base.Promise = function() {}; /** diff --git a/remoting/webapp/unittests/base_unittest.js b/remoting/webapp/unittests/base_unittest.js index 17a1903..c36c6ac 100644 --- a/remoting/webapp/unittests/base_unittest.js +++ b/remoting/webapp/unittests/base_unittest.js @@ -111,6 +111,38 @@ QUnit.asyncTest('Promise.negate should fulfill iff the promise does not.', }); }); +module('base.Deferred'); + +QUnit.asyncTest('resolve() should fulfill the underlying promise.', function() { + function async() { + var deferred = new base.Deferred(); + deferred.resolve('bar'); + return deferred.promise(); + } + + async().then(function(value){ + QUnit.equal(value, 'bar'); + QUnit.start(); + }, function() { + QUnit.ok(false, 'The reject handler should not be invoked.'); + }); +}); + +QUnit.asyncTest('reject() should fail the underlying promise.', function() { + function async() { + var deferred = new base.Deferred(); + deferred.reject('bar'); + return deferred.promise(); + } + + async().then(function(){ + QUnit.ok(false, 'The then handler should not be invoked.'); + }, function(value) { + QUnit.equal(value, 'bar'); + QUnit.start(); + }); +}); + var source = null; var listener = null; |