I've wrote a very simple implementation of Deferred / Promise pattern (inspired by jQuery's $.deferred) for my tiny project (which does not use jQuery)It can handle multiply onSuccess an onFail callbacks with result caching. Example in comments above the code./** * defer() returns methods: *      resolve(data) - request is successfully resolved (returns nothing) *      reject(msg) - request if failed (returns nothing) *      promise() - returns promise function * * promise() returns methods: *      done(successfulCallback) - add on successful callback (returns nothing) *      fail(failCallback) - add on fail callback (returns nothing) * * Example: * * function someHeavyRequest(url) { *      var d = defer(); *      doHeavyRequest(url, *          function (data) { *              // on success *              // ...do something *              d.resolve(data); *          }, *          function (data) { *              // on fail *              // ...do something *              d.reject(data); *          }); *      return d.promise(); * } * * var req = someHeavyRequest(http://some.url/of/request/); * * req.done(function (data) { *      console.log(We got it!); *      console.log(data); * }); * * req.done(function (data) { *      console.log(We got it again without new request!); *      console.log(data); * }); * * req.fail(function (data) { *      console.error(Something wrong); *      console.error(data); * }); * */function defer () {    var status = 0, // 0 = in progress / 1 = successful / -1 = fail        callbacks = { done: [], fail: [] },        args = { resolve: [], reject: [] },        execute = function (callbacks, args) {            var f;            while (callbacks.length) {                f = callbacks.shift();                if (f) f.apply(this, args);            }        };    return {        promise: function () {            return {                done: function (callback) {                    callbacks.done.push(callback);                    if (status === 1) {                        execute(callbacks.done, args.resolve);                    }                },                fail: function (callback) {                    callbacks.fail.push(callback);                    if (status === -1) {                        execute(callbacks.fail,args.reject);                    }                }            };        },        resolve: function () {            status = 1;            args.resolve = arguments;            execute(callbacks.done, args.resolve);        },        reject: function () {            status = -1;            args.reject = arguments;            execute(callbacks.fail, args.reject);        }    };}
Simple Deferred / Promise pattern in JavaScript
javascript;asynchronous
A few things caught my eye:You can call resolve and later call reject too - or the other way around, or call either one multiple times. It should only allow the first resolve/reject call to have an effect.status might as well be a string (pending, resolved, rejected) which obviate the need for a comment explaining the integer values, and would improve readabilityThe if(f) check in execute should probably be a full if(typeof f === 'function') check; lots of values are truthy without being functions. You could also do this check in done/fail and simply ignore/complain about non-function arguments.There's some duplication between done/fail and resolve/reject.For that last one, if the status becomes a string, it's also relative easy use that as a key for organizing the callbacks and arguments.function defer() {  var currentState = 'pending',      callbacks    = { resolved: [], rejected: [] },      args         = []; // only need 1 args array  function execute(state) {    var cb;    while(callbacks[state].length) {      cb = callbacks[state].shift();      if( typeof cb === 'function' ) cb.apply(this, args);    }  }  // generic function factory for done/fail functions  function hook(state) {    return function (cb) {      callbacks[state].push(cb);      if(currentState === state) execute(state);    }  }  // generic function factory for resolve/reject functions  function complete(state) {    return function () {      if(currentState !== 'pending') return;       args = Array.prototype.slice.call(arguments, 0);      currentState = state;      execute(state);    }  }  return {    promise: function () {      return { done: hook('resolved'), fail: hook('rejected') };    },    resolve: complete('resolved'),    reject:  complete('rejected')  };}You may want to add then, always and isPending (or just state) functions. And once you've resolved or rejected, you might as well get rid of the callbacks you're not going to ever use (i.e. if resolved, clear out the reject-callbacks,and vice-versa).Lastly, if you want to emulate jQuery, make it chainable, so you can call x.done(...).fail(...).fail(...).always(...) etc.