Skip to content

Instantly share code, notes, and snippets.

@natalan
Forked from unscriptable/tiny Promise.js
Created August 7, 2012 03:20
Show Gist options
  • Save natalan/3281076 to your computer and use it in GitHub Desktop.
Save natalan/3281076 to your computer and use it in GitHub Desktop.
A minimalist implementation of a javascript promise
// (c) copyright unscriptable.com / John Hann
// License MIT
// For more robust promises, see https://github.com/briancavalier/when.js.
// adding support for limited promises where limited cannot resolve/reject itself
var Promise = function () {
var thens = [],
builder = function (arg){
var Constructor = function () {
this._thens = thens;
};
if (!arg) {
Constructor.prototype = Promise.prototype;
Constructor.prototype.limited = function(){
return builder(1)
};
} else {
Constructor.prototype = {
then: Promise.prototype.then
}
}
Constructor["prototype"]["constructor"] = Promise;
return new Constructor();
};
return builder();
};
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); }
//[malahov] we want to cleanup the closure itself rather than the pointer
this._thens.splice(0,this._thens.length);
}
};
@natalan
Copy link
Author

natalan commented Aug 23, 2012

Making separate repo with unit test for this gist: https://github.com/natalan/Promise

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment