summaryrefslogtreecommitdiffstats
path: root/remoting
diff options
context:
space:
mode:
authorkelvinp@chromium.org <kelvinp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-19 02:32:52 +0000
committerkelvinp@chromium.org <kelvinp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-19 02:34:30 +0000
commitd8391a54250b7c63bcfe410b646bcfa308b519d8 (patch)
treede6508e0e8b53165d0cbc8e775a25301ac95d3ab /remoting
parentf539115f00327c512e447ba5167a88c26ff4e562 (diff)
downloadchromium_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.js77
-rw-r--r--remoting/webapp/unittests/base_unittest.js32
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;