| /* |
| Copyright (c) 2004-2006, The Dojo Foundation |
| All Rights Reserved. |
| |
| Licensed under the Academic Free License version 2.1 or above OR the |
| modified BSD license. For more information on Dojo licensing, see: |
| |
| http://dojotoolkit.org/community/licensing.shtml |
| */ |
| |
| |
| |
| dojo.provide("dojo.Deferred"); |
| dojo.require("dojo.lang.func"); |
| dojo.Deferred = function (canceller) { |
| this.chain = []; |
| this.id = this._nextId(); |
| this.fired = -1; |
| this.paused = 0; |
| this.results = [null, null]; |
| this.canceller = canceller; |
| this.silentlyCancelled = false; |
| }; |
| dojo.lang.extend(dojo.Deferred, {getFunctionFromArgs:function () { |
| var a = arguments; |
| if ((a[0]) && (!a[1])) { |
| if (dojo.lang.isFunction(a[0])) { |
| return a[0]; |
| } else { |
| if (dojo.lang.isString(a[0])) { |
| return dj_global[a[0]]; |
| } |
| } |
| } else { |
| if ((a[0]) && (a[1])) { |
| return dojo.lang.hitch(a[0], a[1]); |
| } |
| } |
| return null; |
| }, makeCalled:function () { |
| var deferred = new dojo.Deferred(); |
| deferred.callback(); |
| return deferred; |
| }, repr:function () { |
| var state; |
| if (this.fired == -1) { |
| state = "unfired"; |
| } else { |
| if (this.fired == 0) { |
| state = "success"; |
| } else { |
| state = "error"; |
| } |
| } |
| return "Deferred(" + this.id + ", " + state + ")"; |
| }, toString:dojo.lang.forward("repr"), _nextId:(function () { |
| var n = 1; |
| return function () { |
| return n++; |
| }; |
| })(), cancel:function () { |
| if (this.fired == -1) { |
| if (this.canceller) { |
| this.canceller(this); |
| } else { |
| this.silentlyCancelled = true; |
| } |
| if (this.fired == -1) { |
| this.errback(new Error(this.repr())); |
| } |
| } else { |
| if ((this.fired == 0) && (this.results[0] instanceof dojo.Deferred)) { |
| this.results[0].cancel(); |
| } |
| } |
| }, _pause:function () { |
| this.paused++; |
| }, _unpause:function () { |
| this.paused--; |
| if ((this.paused == 0) && (this.fired >= 0)) { |
| this._fire(); |
| } |
| }, _continue:function (res) { |
| this._resback(res); |
| this._unpause(); |
| }, _resback:function (res) { |
| this.fired = ((res instanceof Error) ? 1 : 0); |
| this.results[this.fired] = res; |
| this._fire(); |
| }, _check:function () { |
| if (this.fired != -1) { |
| if (!this.silentlyCancelled) { |
| dojo.raise("already called!"); |
| } |
| this.silentlyCancelled = false; |
| return; |
| } |
| }, callback:function (res) { |
| this._check(); |
| this._resback(res); |
| }, errback:function (res) { |
| this._check(); |
| if (!(res instanceof Error)) { |
| res = new Error(res); |
| } |
| this._resback(res); |
| }, addBoth:function (cb, cbfn) { |
| var enclosed = this.getFunctionFromArgs(cb, cbfn); |
| if (arguments.length > 2) { |
| enclosed = dojo.lang.curryArguments(null, enclosed, arguments, 2); |
| } |
| return this.addCallbacks(enclosed, enclosed); |
| }, addCallback:function (cb, cbfn) { |
| var enclosed = this.getFunctionFromArgs(cb, cbfn); |
| if (arguments.length > 2) { |
| enclosed = dojo.lang.curryArguments(null, enclosed, arguments, 2); |
| } |
| return this.addCallbacks(enclosed, null); |
| }, addErrback:function (cb, cbfn) { |
| var enclosed = this.getFunctionFromArgs(cb, cbfn); |
| if (arguments.length > 2) { |
| enclosed = dojo.lang.curryArguments(null, enclosed, arguments, 2); |
| } |
| return this.addCallbacks(null, enclosed); |
| return this.addCallbacks(null, cbfn); |
| }, addCallbacks:function (cb, eb) { |
| this.chain.push([cb, eb]); |
| if (this.fired >= 0) { |
| this._fire(); |
| } |
| return this; |
| }, _fire:function () { |
| var chain = this.chain; |
| var fired = this.fired; |
| var res = this.results[fired]; |
| var self = this; |
| var cb = null; |
| while (chain.length > 0 && this.paused == 0) { |
| var pair = chain.shift(); |
| var f = pair[fired]; |
| if (f == null) { |
| continue; |
| } |
| try { |
| res = f(res); |
| fired = ((res instanceof Error) ? 1 : 0); |
| if (res instanceof dojo.Deferred) { |
| cb = function (res) { |
| self._continue(res); |
| }; |
| this._pause(); |
| } |
| } |
| catch (err) { |
| fired = 1; |
| res = err; |
| } |
| } |
| this.fired = fired; |
| this.results[fired] = res; |
| if ((cb) && (this.paused)) { |
| res.addBoth(cb); |
| } |
| }}); |
| |