class Deferred { public var chain:Array; public var results:Array; public var fired:Number; public var paused:Number; function Deferred() { this.chain = []; this.fired = -1; this.paused = 0; this.results = [null, null]; } function pause():Void { this.paused++; } function unpause():Void { this.paused--; if ((this.paused == 0) && (this.fired >= 0)) { this.fire(); } } function _continue(res:Object):Void { this.resback(res); this.unpause(); } function resback(res:Object):Void { var self:Deferred = this; this.fired = ((res instanceof Error) ? 1 : 0); this.results[this.fired] = res; if (res instanceof Deferred) { var cb:Function = function (nextres:Object) { return self._continue(nextres); } } this.fire(); } function callback(res:Object):Void { this.resback(res); } function errback(res:Object):Void { this.resback(res); } function addBoth(fn:Function):Deferred { return this.addCallbacks(fn, fn); } function addCallback(fn:Function):Deferred { return this.addCallbacks(fn, null); } function addErrback(fn:Function):Deferred { return this.addCallbacks(null, fn); } function addCallbacks(cb:Function, eb:Function):Deferred { this.chain.push([cb, eb]) if (this.fired >= 0) { this.fire(); } return this; } function fire():Void { var chain:Array = this.chain; var fired:Number = this.fired; var res:Object = this.results[fired]; var self:Deferred = this; var cb:Function = null; while (chain.length > 0 && this.paused == 0) { // Array var pair:Object = chain.shift(); try { var f:Function = pair[fired]; res = f(res); fired = ((res instanceof Error) ? 1 : 0); if (res instanceof Deferred) { if (cb == null) { cb = function () { self._continue(); } } this.pause(); res.addBoth(cb); } } catch (err) { fired = 1; res = err; } } this.fired = fired; this.results[fired] = res; } }