Skip to content

Commit

Permalink
More work on node-promise
Browse files Browse the repository at this point in the history
  • Loading branch information
kriszyp committed Feb 16, 2010
1 parent c8f9ae8 commit 51bd882
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 100 deletions.
43 changes: 43 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
Convenience functions for promises, much of this is taken from Tyler Close's ref_send and Kris Kowal's work on promises.
Dual licensed under BSD and AFL.

The workhorse function of this library is the "when" function, which provides a means for normalizing interaction with values and functions that may be a normal synchronous value, or may be a promise (asynchronously fulfilled). The when() function takes a value that may be a promise or a normal value for the first function, and when the value is ready executes the function provided as the second argument (immediately in the case of a non-promise normal value). The value returned from when() is the result of the execution of the provided function, and returns a promise if provided a promise or synchronously returns a normal value if provided a non-promise value. This makes it easy to "chain" computations together. This allows us to write code that is agnostic to sync/async interfaces:

var when = require("promise").when;
function printFirstAndLast(items){
// print the first and last item
when(findFirst(items), sys.puts);
when(findLast(items), sys.puts);
}
function findFirst(items){
// return the first item
return when(items, function(items){
return items[0];
});
}
function findLast(items){
// return the last item
return when(items, function(items){
return items[items.length];
});
}

Now we can do:

> printFirstAndLast([1,2,3,4,5]);
1
5

And we can also provide asynchronous promise:

var promise = new process.Promise();
> printFirstAndLast(promise);
(nothing printed yet)

> promise.emitSuccess([2,4,6,8,10]);
2
10



181 changes: 81 additions & 100 deletions promise.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,8 @@
/**
* Convenience functions for promises, primarily based on the ref_send API
* Convenience functions for promises, much of this is taken from Tyler Close's ref_send
* and Kris Kowal's work on promises.
* Dual licensed under BSD and AFL
*/
function perform(value, async, sync){
try{
if(value && typeof value.then === "function"){
value = async(value);
}
else{
value = sync(value);
}
if(value && typeof value.then === "function"){
return value;
}
var deferred = new process.Promise();
deferred.resolve(value);
return deferred.promise;
}catch(e){
var deferred = new process.Promise();
deferred.reject(e);
return deferred.promise;
}

}
/**
* Promise manager to make it easier to consume promises
*/

/**
* Registers an observer on a promise.
Expand All @@ -35,12 +13,37 @@ function perform(value, async, sync){
* @return promise for the return value from the invoked callback
*/
exports.whenPromise = function(value, resolvedCallback, rejectCallback, progressCallback){
return perform(value, function(value){
return value.then(resolvedCallback, rejectCallback, progressCallback);
},
function(value){
return resolvedCallback(value);
});
try{
var returnValue;
if (value && (typeof value.addCallback === "function" || typeof value.then === "function")){
if (typeof value.addCallback === "function"){
value.addCallback(function(value){
resolvedCallback(value);
});
value.addErrback(rejectCallback);
var deferred = new process.Promise();
deferred.resolve(value);
return deferred.promise;
}
else {
value = value.then(resolvedCallback, rejectCallback, progressCallback);
}
}
else{
value = resolvedCallback(value);
}
if(value && typeof value.then === "function"){
return value;
}
var deferred = new process.Promise();
deferred.resolve(value);
return deferred;
}
catch(e){
var deferred = new process.Promise();
deferred.reject(e);
return deferred.promise;
}
};
/**
* Registers an observer on a promise.
Expand All @@ -52,58 +55,12 @@ exports.whenPromise = function(value, resolvedCallback, rejectCallback, progress
* is a non-promise value
*/
exports.when = function(value, resolvedCallback, rejectCallback, progressCallback){
if(value && typeof value.then === "function"){
return exports.whenPromise(value, resolvedCallback, rejectCallback, progressCallback);
}
return resolvedCallback(value);
if(value && (typeof value.addCallback === "function" || typeof value.then === "function")){
return exports.whenPromise(value, resolvedCallback, rejectCallback, progressCallback);
}
return resolvedCallback(value);
};

/**
* Gets the value of a property in a future turn.
* @param target promise or value for target object
* @param property name of property to get
* @return promise for the property value
*/
exports.get = function(target, property){
return perform(target, function(target){
return target.get(property);
},
function(target){
return target[property]
});
};

/**
* Invokes a method in a future turn.
* @param target promise or value for target object
* @param methodName name of method to invoke
* @param args array of invocation arguments
* @return promise for the return value
*/
exports.post = function(target, methodName, args){
return perform(target, function(target){
return target.call(property, args);
},
function(target){
return target[methodName].apply(target, args);
});
};

/**
* Sets the value of a property in a future turn.
* @param target promise or value for target object
* @param property name of property to set
* @param value new value of property
* @return promise for the return value
*/
exports.put = function(target, property, value){
return perform(target, function(target){
return target.put(property, value);
},
function(target){
return target[property] = value;
});
};


/**
Expand All @@ -119,25 +76,49 @@ exports.wait = process.Promise.wait;
/**
* Takes an array of promises and returns a promise that that is fulfilled once all
* the promises in the array are fulfilled
* @param group The array of promises
* @param array The array of promises
* @return the promise that is fulfilled when all the array is fulfilled
*/
exports.all = function(array){
var deferred = defer();
if(!(array instanceof Array)){
array = Array.prototype.slice.call(arguments);
}
var fulfilled, length = array.length;
var results = [];
array.forEach(function(promise, index){
exports.when(promise, function(value){
results[index] = value;
fulfilled++;
if(fulfilled === length){
deferred.resolve(results);
}
},
deferred.reject);
});
return deferred.promise;
};

/**
* Takes an array of promises and returns the first promise that that is fulfilled
* the promises in the array are fulfilled
* @param array The array of promises
* @return the promise that is fulfilled when all the array is fulfilled
*/
exports.group = function(group){
var deferred = defer();
if(!(group instanceof Array)){
group = Array.prototype.slice.call(arguments);
}
var fulfilled, length = group.length;
var results = [];
group.forEach(function(promise, index){
exports.when(promise, function(value){
results[index] = value;
fulfilled++;
if(fulfilled === length){
deferred.resolve(results);
}
},
deferred.reject);
});
return deferred.promise;
exports.first = function(array){
var deferred = defer();
if(!(array instanceof Array)){
array = Array.prototype.slice.call(arguments);
}
var fulfilled;
array.forEach(function(promise, index){
exports.when(promise, function(value){
if (!done) {
fulfilled = true;
deferred.resolve(value);
}
},
deferred.reject);
});
return deferred.promise;
};

0 comments on commit 51bd882

Please sign in to comment.