1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
6 * @fileoverview This implementes a future promise class.
9 cr.define('cr', function() {
12 * Sentinel used to mark a value as pending.
15 var PENDING_VALUE = {};
18 * Creates a future promise.
19 * @param {*=} opt_value The value to set the promise to. If set completes
20 * the promise immediately.
23 function Promise(opt_value) {
25 * An array of the callbacks.
26 * @type {!Array.<!Function>}
31 if (arguments.length > 0)
32 this.value = opt_value;
41 value_: PENDING_VALUE,
44 * The value of the future promise. Accessing this before the promise has
45 * been fulfilled will throw an error. If this is set to an exception
46 * accessing this will throw as well.
50 return this.done ? this.value_ : undefined;
55 for (var i = 0; i < this.callbacks_.length; i++) {
56 this.callbacks_[i].call(null, value);
58 this.callbacks_.length = 0;
63 * Whether the future promise has been fulfilled.
67 return this.value_ !== PENDING_VALUE;
71 * Adds a listener to the future promise. The function will be called when
72 * the promise is fulfilled. If the promise is already fullfilled this will
73 * never call the function.
74 * @param {!Function} fun The function to call.
76 addListener: function(fun) {
80 this.callbacks_.push(fun);
84 * Removes a previously added listener from the future promise.
85 * @param {!Function} fun The function to remove.
87 removeListener: function(fun) {
88 var i = this.callbacks_.indexOf(fun);
90 this.callbacks_.splice(i, 1);
94 * If the promise is done then this returns the string representation of
96 * @return {string} The string representation of the promise.
99 toString: function() {
101 return String(this.value);
103 return '[object Promise]';
107 * Override to allow arithmetic.
110 valueOf: function() {
116 * When a future promise is done call {@code fun}. This also calls the
117 * function if the promise has already been fulfilled.
118 * @param {!Promise} p The promise.
119 * @param {!Function} fun The function to call when the promise is fulfilled.
121 Promise.when = function(p, fun) {
126 * Creates a new promise the will be fulfilled after {@code t} ms.
127 * @param {number} t The time to wait before the promise is fulfilled.
128 * @param {*=} opt_value The value to return after the wait.
129 * @return {!Promise} The new future promise.
131 Promise.wait = function(t, opt_value) {
133 window.setTimeout(function() {
140 * Creates a new future promise that is fulfilled when any of the promises are
141 * fulfilled. The value of the returned promise will be the value of the first
143 * @param {...!Promise} var_args The promises used to build up the new
145 * @return {!Promise} The new promise that will be fulfilled when any of the
146 * passed in promises are fulfilled.
148 Promise.any = function(var_args) {
153 for (var i = 0; i < arguments.length; i++) {
154 arguments[i].addListener(f);
160 * Creates a new future promise that is fulfilled when all of the promises are
161 * fulfilled. The value of the returned promise is an array of the values of
162 * the promises passed in.
163 * @param {...!Promise} var_args The promises used to build up the new
165 * @return {!Promise} The promise that wraps all the promises in the array.
167 Promise.all = function(var_args) {
169 var args = Array.prototype.slice.call(arguments);
170 var count = args.length;
179 p.value = args.map(function(argP) {
185 // Do not use count here since count may be decremented in the call to
186 // addListener if the promise is already done.
187 for (var i = 0; i < args.length; i++) {
188 args[i].addListener(f);
195 * Wraps an event in a future promise.
196 * @param {!EventTarget} target The object that dispatches the event.
197 * @param {string} type The type of the event.
198 * @param {boolean=} opt_useCapture Whether to listen to the capture phase or
200 * @return {!Promise} The promise that will be fulfilled when the event is
203 Promise.event = function(target, type, opt_useCapture) {
205 target.addEventListener(type, function(e) {