diff options
Diffstat (limited to 'js/src/Ice/Promise.js')
-rw-r--r-- | js/src/Ice/Promise.js | 295 |
1 files changed, 31 insertions, 264 deletions
diff --git a/js/src/Ice/Promise.js b/js/src/Ice/Promise.js index ec61f0dcdef..464bbad5470 100644 --- a/js/src/Ice/Promise.js +++ b/js/src/Ice/Promise.js @@ -7,291 +7,58 @@ // // ********************************************************************** -var Ice = require("../Ice/ModuleRegistry").Ice; -Ice.__M.require(module, - [ - "../Ice/Class", - "../Ice/TimerUtil" - ]); +const Ice = require("../Ice/Timer").Ice; +const Timer = Ice.Timer; -var Timer = Ice.Timer; - -// -// Promise State -// -var State = {Pending: 0, Success: 1, Failed: 2}; - -var resolveImp = function(self, listener) +class P extends Promise { - var callback = self.__state === State.Success ? listener.onResponse : listener.onException; - try + constructor(cb) { - if(typeof callback !== "function") - { - listener.promise.setState(self.__state, self._args); - } - else - { - var result = callback.apply(null, self._args); - - // - // Callback can return a new promise. - // - if(result && typeof result.then == "function") + let res, rej; + super((resolve, reject) => { - result.then( - function() - { - var args = arguments; - listener.promise.succeed.apply(listener.promise, args); - }, - function() - { - var args = arguments; - listener.promise.fail.apply(listener.promise, args); - }); - } - else - { - listener.promise.succeed(result); - } - } - } - catch(e) - { - listener.promise.fail.call(listener.promise, e); - } -}; + res = resolve; + rej = reject; -var Promise = Ice.Class({ - __init__: function() - { - this.__state = State.Pending; - this.__listeners = []; - }, - then: function(onResponse, onException) - { - var promise = new Promise(); - var self = this; - // - // Use setImmediate so the listeners are not resolved until the call stack is empty. - // - Timer.setImmediate( - function() - { - self.__listeners.push( - { - promise:promise, - onResponse:onResponse, - onException:onException - }); - self.resolve(); - }); - return promise; - }, - exception: function(onException) - { - return this.then(null, onException); - }, - finally: function(cb) - { - var p = new Promise(); - var self = this; - - var finallyHandler = function(method) - { - return function() - { - var args = arguments; - try - { - var result = cb.apply(null, args); - if(result && typeof result.then == "function") - { - var handler = function(){ method.apply(p, args); }; - result.then(handler).exception(handler); - } - else - { - method.apply(p, args); - } - } - catch(e) + if(cb !== undefined) { - method.apply(p, args); + cb(resolve, reject); } - }; - }; - - Timer.setImmediate( - function(){ - self.then(finallyHandler(p.succeed), finallyHandler(p.fail)); }); - return p; - }, - delay: function(ms) - { - var p = new Promise(); - - var self = this; - - var delayHandler = function(promise, method) - { - return function() - { - var args = arguments; - Timer.setTimeout( - function() - { - method.apply(promise, args); - }, - ms); - }; - }; - - Timer.setImmediate(function() - { - self.then(delayHandler(p, p.succeed), delayHandler(p, p.fail)); - }); - return p; - }, - resolve: function() - { - if(this.__state === State.Pending) - { - return; - } - var obj; - while((obj = this.__listeners.pop())) - { - // - // We use a separate function here to capture the listeners - // in the loop. - // - resolveImp(this, obj); - } - }, - setState: function(state, args) - { - if(this.__state === State.Pending && state !== State.Pending) - { - this.__state = state; - this._args = args; - // - // Use setImmediate so the listeners are not resolved until the call stack is empty. - // - var self = this; - Timer.setImmediate(function(){ self.resolve(); }); - } - }, - succeed: function() - { - var args = arguments; - this.setState(State.Success, args); - return this; - }, - fail: function() - { - var args = arguments; - this.setState(State.Failed, args); - return this; - }, - succeeded: function() - { - return this.__state === State.Success; - }, - failed: function() - { - return this.__state === State.Failed; - }, - completed: function() - { - return this.__state !== State.Pending; + this.resolve = res; + this.reject = rej; } -}); - -// -// Create a new promise object that is fulfilled when all the promise arguments -// are fulfilled or is rejected when one of the promises is rejected. -// -Promise.all = function() -{ - // If only one argument is provided, check if the argument is an array - if(arguments.length === 1 && arguments[0] instanceof Array) + + finally(cb) { - return Promise.all.apply(this, arguments[0]); + return this.then( + (value) => P.resolve(cb()).then(() => value), + (reason) => P.resolve(cb()).then(() => { throw reason; })); } - var promise = new Promise(); - var promises = Array.prototype.slice.call(arguments); - var results = new Array(arguments.length); - - var pending = promises.length; - if(pending === 0) + delay(ms) { - promise.succeed.apply(promise, results); + return this.then( + value => new P((resolve, reject) => Timer.setTimeout(() => resolve(value), ms)), + reason => new P((resolve, reject) => Timer.setTiemout(() => reject(reason), ms))); } - for(var i = 0; i < promises.length; ++i) + + static get [Symbol.species]() { - // - // Create an anonymous function to capture the loop index - // - - /*jshint -W083 */ - (function(j) - { - if(promises[j] && typeof promises[j].then == "function") - { - promises[j].then( - function() - { - results[j] = arguments; - pending--; - if(pending === 0) - { - promise.succeed.apply(promise, results); - } - }, - function() - { - promise.fail.apply(promise, arguments); - }); - } - else - { - results[j] = promises[j]; - pending--; - if(pending === 0) - { - promise.succeed.apply(promise, results); - } - } - }(i)); - /*jshint +W083 */ + return P; } - return promise; -}; - -Promise.try = function(onResponse) -{ - return new Promise().succeed().then(onResponse); -}; -Promise.delay = function(ms) -{ - if(arguments.length > 1) + static delay(ms, value) { - var p = new Promise(); - var args = Array.prototype.slice.call(arguments); - ms = args.pop(); - return p.succeed.apply(p, args).delay(ms); + return new P(resolve => Timer.setTimeout(() => resolve(value), ms)); } - else + + static try(cb) { - return new Promise().succeed().delay(ms); + return P.resolve().then(cb); } -}; +} -Ice.Promise = Promise; +Ice.Promise = P; module.exports.Ice = Ice; |