// (c) copyright unscriptable.com / John Hann // License MIT // For more robust promises, see https://github.com/briancavalier/when.js. function Promise () { this._thens = []; } Promise.prototype = { /* This is the "front end" API. */ // then(onResolve, onReject): Code waiting for this promise uses the // then() method to be notified when the promise is complete. There // are two completion callbacks: onReject and onResolve. A more // robust promise implementation will also have an onProgress handler. then: function (onResolve, onReject) { // capture calls to then() this._thens.push({ resolve: onResolve, reject: onReject }); }, // Some promise implementations also have a cancel() front end API that // calls all of the onReject() callbacks (aka a "cancelable promise"). // cancel: function (reason) {}, /* This is the "back end" API. */ // resolve(resolvedValue): The resolve() method is called when a promise // is resolved (duh). The resolved value (if any) is passed by the resolver // to this method. All waiting onResolve callbacks are called // and any future ones are, too, each being passed the resolved value. resolve: function (val) { this._complete('resolve', val); }, // reject(exception): The reject() method is called when a promise cannot // be resolved. Typically, you'd pass an exception as the single parameter, // but any other argument, including none at all, is acceptable. // All waiting and all future onReject callbacks are called when reject() // is called and are passed the exception parameter. reject: function (ex) { this._complete('reject', ex); }, // Some promises may have a progress handler. The back end API to signal a // progress "event" has a single parameter. The contents of this parameter // could be just about anything and is specific to your implementation. // progress: function (data) {}, /* "Private" methods. */ _complete: function (which, arg) { // switch over to sync then() this.then = which === 'resolve' ? function (resolve, reject) { resolve && resolve(arg); } : function (resolve, reject) { reject && reject(arg); }; // disallow multiple calls to resolve or reject this.resolve = this.reject = function () { throw new Error('Promise already completed.'); }; // complete all waiting (async) then()s var aThen, i = 0; while (aThen = this._thens[i++]) { aThen[which] && aThen[which](arg); } delete this._thens; } };