Skip to content

Instantly share code, notes, and snippets.

@getify
Created February 22, 2010 22:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save getify/311586 to your computer and use it in GitHub Desktop.
Save getify/311586 to your computer and use it in GitHub Desktop.
var promise = (function(){
var undef;
function Promise(){}
Promise.prototype.constructor = Promise;
return function(cb) {
var publicAPI, queue = [], old_ret, promise_fulfilled = false;
function fulfill(val) {
var ret_val = val;
if (typeof ret_val != "undefined") old_ret = ret_val;
try {
return val;
}
finally {
for (var i=0,len=queue.length; i<len; i++) {
if (typeof ret_val != "undefined") old_ret = ret_val;
ret_val = queue[0].call(publicAPI,ret_val);
if (typeof ret_val == "undefined") { ret_val = old_ret; }
else if (ret_val && !(ret_val instanceof Promise) old_ret = ret_val;
queue.shift();
if (ret_val && ret_val instanceof Promise) {
promise_fulfilled = false;
ret_val.then(function(P){ promise_fulfilled = true; return (old_ret = fulfill(P.value)); });
break;
}
}
}
}
publicAPI = new Promise();
publicAPI.then = function(cb){
if (typeof cb == "function") queue[queue.length] = function(val){ return cb.call(publicAPI,{value:val}); }; // then() callback
else queue[queue.length] = function(val){ return cb; }; // then() value
if (promise_fulfilled) fulfill(old_ret);
return publicAPI;
};
if (cb == null) { // empty promise
promise_fulfilled = true;
}
else if (typeof cb == "function") { // promise callback
cb.call(publicAPI,{fulfill:function(val){
promise_fulfilled = true;
fulfill.call(publicAPI,val);
},value:undef});
}
else { // immediate promise value
promise_fulfilled = true;
return publicAPI.then(cb);
}
return publicAPI;
};
})();
function xhrcall() {
return promise(function(P){
var xhr = new XMLHttpRequest();
xhr.open("GET","some.tld/something");
xhr.onreadystatechange = function(){
if (xhr.readyState==4) P.fulfill(xhr.responseText);
};
xhr.send();
});
}
xhrcall()
.then(function(P){
alert(P.value);
});
function delay(secs) {
return promise(function(P){
setTimeout(P.fulfill,secs*1000);
});
}
delay(5)
.then("Hello World!")
.then(function(P){
alert(P.value);
});
// run xhrcall, then delay 10 secs, then alert the xhr response
xhrcall()
.then(function(P){
return delay(10)
.then(P.value)
;
})
.then(function(P){
alert(P.value);
});
// run xhrcall and the delay in parallel, wait for both to fulfill,
// then alert the xhr response
var a = xhrcall();
var b = delay(10);
a.then(function(P){
return b.then(P.value);
})
.then(function(P){
alert(P.value);
});
// include: jQuery
function listenTo(whichElem) {
return promise(function(P){
$(whichElem).click(function(){P.fulfill(this);});
});
}
listenTo("a")
.then(function(P){
var elem = P.value;
alert(elem.href);
});
function doSync(msg){
return promise(msg); // empty/immediate promise, for chaining
}
function doAsync(secs){
return delay(secs);
}
doSync("starting...")
.then(function(P){
alert(P.value);
return doAsync(3);
})
.then(function(P){
alert("...all done!");
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment