OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2010 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. |
| 4 |
| 5 /** |
| 6 * @fileoverview This implementes a future promise class. |
| 7 */ |
| 8 |
| 9 cr.define('cr', function() { |
| 10 |
| 11 /** |
| 12 * Sentinel used to mark a value as pending. |
| 13 */ |
| 14 const PENDING_VALUE = {}; |
| 15 |
| 16 /** |
| 17 * Creates a future promise. |
| 18 * @param {Function=} opt_callback Callback. |
| 19 * @constructor |
| 20 */ |
| 21 function Promise(opt_callback) { |
| 22 /** |
| 23 * An array of the callbacks. |
| 24 * @type {!Array.<!Function>} |
| 25 * @private |
| 26 */ |
| 27 this.callbacks_ = opt_callback ? [opt_callback] : []; |
| 28 } |
| 29 |
| 30 Promise.prototype = { |
| 31 /** |
| 32 * The current value. |
| 33 * @type {*} |
| 34 * @private |
| 35 */ |
| 36 value_: PENDING_VALUE, |
| 37 |
| 38 /** |
| 39 * The value of the future promise. Accessing this before the promise has |
| 40 * been fulfilled will throw an error. If this is set to an exception |
| 41 * accessing this will throw as well. |
| 42 * @type {*} |
| 43 */ |
| 44 get value() { |
| 45 return this.done ? this.value_ : undefined; |
| 46 }, |
| 47 set value(value) { |
| 48 if (!this.done) { |
| 49 this.value_ = value; |
| 50 for (var i = 0; i < this.callbacks_.length; i++) { |
| 51 this.callbacks_[i].call(null, value); |
| 52 } |
| 53 this.callbacks_.length = 0; |
| 54 } |
| 55 }, |
| 56 |
| 57 /** |
| 58 * Whether the future promise has been fulfilled. |
| 59 * @type {boolean} |
| 60 */ |
| 61 get done() { |
| 62 return this.value_ !== PENDING_VALUE; |
| 63 }, |
| 64 |
| 65 /** |
| 66 * Adds a listener to the future promise. The function will be called when |
| 67 * the promise is fulfilled. If the promise is already fullfilled this will |
| 68 * never call the function. |
| 69 * @param {!Function} fun The function to call. |
| 70 */ |
| 71 addListener: function(fun) { |
| 72 if (this.done) |
| 73 fun(this.value); |
| 74 else |
| 75 this.callbacks_.push(fun); |
| 76 }, |
| 77 |
| 78 /** |
| 79 * Removes a previously added listener from the future promise. |
| 80 * @param {!Function} fun The function to remove. |
| 81 */ |
| 82 removeListener: function(fun) { |
| 83 var i = this.callbacks_.indexOf(fun); |
| 84 if (i >= 0) |
| 85 this.callbacks_.splice(i, 1); |
| 86 }, |
| 87 |
| 88 /** |
| 89 * If the promise is done then this returns the string representation of |
| 90 * the value. |
| 91 * @return {string} The string representation of the promise. |
| 92 * @override |
| 93 */ |
| 94 toString: function() { |
| 95 if (this.done) |
| 96 return String(this.value); |
| 97 else |
| 98 return '[object Promise]'; |
| 99 }, |
| 100 |
| 101 /** |
| 102 * Override to allow arithmetic. |
| 103 * @override |
| 104 */ |
| 105 valueOf: function() { |
| 106 return this.value; |
| 107 } |
| 108 }; |
| 109 |
| 110 /** |
| 111 * When a future promise is done call {@code fun}. This also calls the |
| 112 * function if the promise has already been fulfilled. |
| 113 * @param {!Promise} p The promise. |
| 114 * @param {!Function} fun The function to call when the promise is fulfilled. |
| 115 */ |
| 116 Promise.when = function(p, fun) { |
| 117 p.addListener(fun); |
| 118 }; |
| 119 |
| 120 /** |
| 121 * Creates a new promise the will be fulfilled after {@code t} ms. |
| 122 * @param {number} t The time to wait before the promise is fulfilled. |
| 123 * @param {*=} opt_value The value to return after the wait. |
| 124 * @return {!Promise} The new future promise. |
| 125 */ |
| 126 Promise.wait = function(t, opt_value) { |
| 127 var p = new Promise; |
| 128 window.setTimeout(function() { |
| 129 p.value = opt_value; |
| 130 }, t); |
| 131 return p; |
| 132 }; |
| 133 |
| 134 /** |
| 135 * Creates a new future promise that is fulfilled when any of the promises are |
| 136 * fulfilled. |
| 137 * @param {...!Promise} var_args The promises used to build up the new |
| 138 * promise. |
| 139 * @return {!Promise} The new promise that will be fulfilled when any of th |
| 140 * passed in promises are fulfilled. |
| 141 */ |
| 142 Promise.any = function(var_args) { |
| 143 var p = new Promise; |
| 144 function f(v) { |
| 145 p.value = v; |
| 146 } |
| 147 for (var i = 0; i < arguments.length; i++) { |
| 148 arguments[i].addListener(f); |
| 149 } |
| 150 return p; |
| 151 }; |
| 152 |
| 153 /** |
| 154 * Wraps an event in a future promise. |
| 155 * @param {!EventTarget} target The object that dispatches the event. |
| 156 * @param {string} type The type of the event. |
| 157 * @param {boolean=} opt_useCapture Whether to listen to the capture phase or |
| 158 * the bubble phase. |
| 159 * @return {!Promise} The promise that will be fulfilled when the event is |
| 160 * dispatched. |
| 161 */ |
| 162 Promise.event = function(target, type, opt_useCapture) { |
| 163 var p = new Promise; |
| 164 target.addEventListener(type, function(e) { |
| 165 p.value = e; |
| 166 }, opt_useCapture); |
| 167 return p; |
| 168 }; |
| 169 |
| 170 return { |
| 171 Promise: Promise |
| 172 }; |
| 173 })(); |
OLD | NEW |