Skip to content

Commit

Permalink
initial version
Browse files Browse the repository at this point in the history
  • Loading branch information
dfilatov committed Dec 9, 2012
0 parents commit 76604cd
Show file tree
Hide file tree
Showing 7 changed files with 639 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules/
coverage
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
test:
./node_modules/.bin/nodeunit test

.PHONY: test
1 change: 1 addition & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('./lib/promise');
156 changes: 156 additions & 0 deletions lib/promise.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
var undef,
nextTick = process.nextTick,
isFunction = function(obj) {
return typeof obj === 'function';
};

var Promise = module.exports = function() {
if(!(this instanceof Promise)) {
return new Promise();
}

this._isResolved = false;
this._isRejected = false;

this._res = undef;

this._resolvedCallbacks = [];
this._rejectedCallbacks = [];
};

Promise.prototype = {
valueOf : function() {
return this._res;
},

isResolved : function() {
return this._isResolved;
},

resolve : function(val) {
if(this._isResolved || this._isRejected) {
return;
}

this._isResolved = true;
this._res = val;

callCallbacks(this._resolvedCallbacks, val);
delete this._resolvedCallbacks;
},

isRejected : function() {
return this._isRejected;
},

reject : function(error) {
if(this._isResolved || this._isRejected) {
return;
}

this._isRejected = true;
this._res = error;

callCallbacks(this._rejectedCallbacks, error, true);
delete this._rejectedCallbacks;
},

then : function(onResolved, onRejected) {
var promise = new Promise(),
cb;

if(!this._isRejected) {
cb = { promise : promise, fn : onResolved };
this._isResolved?
callCallbacks([cb], this._res) :
this._resolvedCallbacks.push(cb);
}

if(!this._isResolved) {
cb = { promise : promise, fn : onRejected };
this._isRejected?
callCallbacks([cb], this._error, true) :
this._rejectedCallbacks.push(cb);
}

return promise;
}
};

Promise.isPromise = function(obj) {
return obj instanceof this;
};

Promise.all = function(promises) {
var promise = new this(),
len = promises.length,
progress = function() {
if(!--len) {
promise.resolve(promises);
}
},
i = 0;

while(i < len) {
promises[i++].then(progress, progress);
}

return promise;
};

Promise.timeout = function(origPromise, timeout) {
var promise = new this(),
timer = setTimeout(function() {
promise.reject(new Error('timed out'));
}, timeout);

origPromise.then(
function(res) {
clearTimeout(timer);
promise.resolve(res);
},
function(error) {
clearTimeout(timer);
promise.reject(error);
});

return promise;
};

function callCallbacks(callbacks, arg, isRejected) {
callbacks.length && nextTick(function() {
var i = 0, len = callbacks.length, cb;
while(i < len) {
var promise = (cb = callbacks[i++]).promise,
fn = cb.fn;

if(isFunction(fn)) {
var res;
try {
res = fn(arg);
}
catch(e) {
promise.reject(e);
continue;
}

Promise.isPromise(res)?
(function(promise) {
res.then(
function(val) {
promise.resolve(val);
},
function(error) {
promise.reject(error);
})
})(promise) :
promise.resolve(res);
}
else {
isRejected?
promise.reject(arg) :
promise.resolve(arg);
}
}
});
}
26 changes: 26 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name" : "jspromise",
"version" : "0.0.1",
"description" : "Promises/A+ proposal compatible promises library",
"homepage" : "https://github.com/dfilatov/jspromise",
"keywords" : ["promise"],
"author" : "Dmitry Filatov <[email protected]>",
"contributors" : [{
"name" : "Dmitry Filatov",
"email" : "[email protected]"
}],
"repository":{
"type" : "git",
"url" : "http://github.com/dfilatov/jspromise.git"
},
"dependencies": {},
"devDependencies": {
"nodeunit" : "",
"istanbul" : ""
},
"main" : "index",
"engines" : { "node" : ">= 0.4.0" },
"scripts" : {
"test" : "./node_modules/istanbul/lib/cli.js test test-runner.js"
}
}
1 change: 1 addition & 0 deletions test-runner.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
require('nodeunit').reporters.default.run(['test']);
Loading

0 comments on commit 76604cd

Please sign in to comment.