Comparing version 0.2.2 to 0.3.0
122
kew.js
/** | ||
* An object representing a "promise" for a future value | ||
* | ||
* @param {function(Object)} onSuccess a function to handle successful | ||
* @param {?function(*, *)=} onSuccess a function to handle successful | ||
* resolution of this promise | ||
* @param {function(Error)} onFail a function to handle failed | ||
* @param {function(!Error, *)=} onFail a function to handle failed | ||
* resolution of this promise | ||
@@ -22,3 +22,4 @@ * @constructor | ||
* Specify that the current promise should have a specified context | ||
* @param {Object} context context | ||
* @param {*} context context | ||
* @private | ||
*/ | ||
@@ -39,3 +40,3 @@ Promise.prototype._useContext = function (context) { | ||
* Set the context for all promise handlers to follow | ||
* @param {context} context An arbitrary context | ||
* @param {*} context An arbitrary context | ||
*/ | ||
@@ -50,3 +51,3 @@ Promise.prototype.setContext = function (context) { | ||
* Get the context for a promise | ||
* @return {Object} the context set by setContext | ||
* @return {*} the context set by setContext | ||
*/ | ||
@@ -60,3 +61,3 @@ Promise.prototype.getContext = function () { | ||
* | ||
* @param {Object} data | ||
* @param {*} data | ||
*/ | ||
@@ -70,3 +71,3 @@ Promise.prototype.resolve = function (data) { | ||
if (this._promises) { | ||
for (var i = 0; i < this._promises.length; i += 1) { | ||
for (i = 0; i < this._promises.length; i += 1) { | ||
data._chainPromise(this._promises[i]) | ||
@@ -78,3 +79,3 @@ } | ||
if (this._onComplete) { | ||
for (var i = 0; i < this._onComplete.length; i+= 1) { | ||
for (i = 0; i < this._onComplete.length; i+= 1) { | ||
data.fin(this._onComplete[i]) | ||
@@ -111,3 +112,3 @@ } | ||
* | ||
* @param {Error} e | ||
* @param {!Error} e | ||
*/ | ||
@@ -145,5 +146,5 @@ Promise.prototype.reject = function (e) { | ||
* | ||
* @param {function(Object)} onSuccess | ||
* @param {?function(Error)} onFail | ||
* @return {Promise} returns a new promise with the output of the onSuccess or | ||
* @param {?function(*, *)} onSuccess | ||
* @param {function(!Error, *)=} onFail | ||
* @return {!Promise} returns a new promise with the output of the onSuccess or | ||
* onFail handler | ||
@@ -164,4 +165,4 @@ */ | ||
* | ||
* @param {function(Error)} onFail | ||
* @return {Promise} returns a new promise with the output of the onFail handler | ||
* @param {function(!Error, *=)} onFail | ||
* @return {!Promise} returns a new promise with the output of the onFail handler | ||
*/ | ||
@@ -177,3 +178,3 @@ Promise.prototype.fail = function (onFail) { | ||
* @param {function()} onComplete | ||
* @return {Promise} returns the current promise | ||
* @return {!Promise} returns the current promise | ||
*/ | ||
@@ -200,3 +201,3 @@ Promise.prototype.fin = function (onComplete) { | ||
* | ||
* @return {Promise} returns the current promise | ||
* @return {!Promise} returns the current promise | ||
*/ | ||
@@ -214,3 +215,3 @@ Promise.prototype.end = function () { | ||
* | ||
* @param {Object} data the input | ||
* @param {*} data the input | ||
*/ | ||
@@ -233,3 +234,4 @@ Promise.prototype._withInput = function (data) { | ||
* | ||
* @param {Error} e | ||
* @param {!Error} e | ||
* @private | ||
*/ | ||
@@ -240,4 +242,4 @@ Promise.prototype._withError = function (e) { | ||
this.resolve(this._failFn(e, this._currentContext)) | ||
} catch (e) { | ||
this.reject(e) | ||
} catch (thrown) { | ||
this.reject(thrown) | ||
} | ||
@@ -253,3 +255,4 @@ } else this.reject(e) | ||
* | ||
* @param {Promise} the promise to chain | ||
* @param {!Promise} promise the promise to chain | ||
* @private | ||
*/ | ||
@@ -277,5 +280,5 @@ Promise.prototype._chainPromise = function (promise) { | ||
* | ||
* @param {Promise} deferred a promise that looks like a deferred | ||
* @param {Error} err an optional error | ||
* @param {Object} data optional data | ||
* @param {!Promise} deferred a promise that looks like a deferred | ||
* @param {Error=} err an optional error | ||
* @param {*=} data optional data | ||
*/ | ||
@@ -291,3 +294,3 @@ function resolver(deferred, err, data) { | ||
* | ||
* @return {function(Error, Object)} node-style callback | ||
* @return {function(Error, *)} node-style callback | ||
*/ | ||
@@ -306,3 +309,3 @@ Promise.prototype.makeNodeResolver = function () { | ||
* | ||
* @param {Object} obj The object to test | ||
* @param {*} obj The object to test | ||
* @return {boolean} Whether the object is a promise | ||
@@ -318,3 +321,3 @@ */ | ||
* | ||
* @param {Object} obj The object to test | ||
* @param {*} obj The object to test | ||
* @return {boolean} Whether the object is a promise-like object | ||
@@ -329,4 +332,4 @@ */ | ||
* | ||
* @param {Object} data data to resolve the promise with | ||
* @return {Promise} | ||
* @param {*} data data to resolve the promise with | ||
* @return {!Promise} | ||
*/ | ||
@@ -342,4 +345,4 @@ function resolve(data) { | ||
* | ||
* @param {Error} e error to reject the promise with | ||
* @return {Promise} | ||
* @param {!Error} e error to reject the promise with | ||
* @return {!Promise} | ||
*/ | ||
@@ -356,6 +359,6 @@ function reject(e) { | ||
* | ||
* @param {Array.<Object>} arr | ||
* @param {!Array} arr | ||
* @param {number} idx | ||
* @param {Object} val | ||
* @return {Object} the val that's being injected into the array | ||
* @param {*} val | ||
* @return {*} the val that's being injected into the array | ||
*/ | ||
@@ -371,4 +374,4 @@ function replaceEl(arr, idx, val) { | ||
* | ||
* @param {Array.<Promise|Object>} promises | ||
* @return {Promise.<Array.<Object>>} | ||
* @param {!Array} promises | ||
* @return {!Promise.<!Array>} | ||
*/ | ||
@@ -382,3 +385,2 @@ function all(promises) { | ||
var outputs = [] | ||
var counter = 0 | ||
var finished = false | ||
@@ -389,3 +391,3 @@ var promise = new Promise() | ||
for (var i = 0; i < promises.length; i += 1) { | ||
if (!promises[i] || !isPromise(promises[i])) { | ||
if (!promises[i] || !isPromiseLike(promises[i])) { | ||
outputs[i] = promises[i] | ||
@@ -421,3 +423,3 @@ counter -= 1 | ||
* | ||
* @return {Promise} | ||
* @return {!Promise} | ||
*/ | ||
@@ -432,4 +434,4 @@ function defer() { | ||
* @param {number} delayMs | ||
* @param {Object} returnVal | ||
* @return {Promise.<Object>} returns returnVal | ||
* @param {*} returnVal | ||
* @return {!Promise} returns returnVal | ||
*/ | ||
@@ -445,22 +447,43 @@ function delay(delayMs, returnVal) { | ||
/** | ||
* Return a promise which will evaluate the function fn with the provided args | ||
* Return a promise which will evaluate the function fn in a future turn with | ||
* the provided args | ||
* | ||
* @param {function} fn | ||
* @param {Object} var_args a variable number of arguments | ||
* @return {Promise} | ||
* @param {function()} fn | ||
* @param {...} var_args a variable number of arguments | ||
* @return {!Promise} | ||
*/ | ||
function fcall(fn, var_args) { | ||
var rootArgs = Array.prototype.slice.call(arguments, 1) | ||
var defer = new Promise() | ||
defer.resolve(fn.apply(null, Array.prototype.slice.call(arguments, 1))) | ||
process.nextTick(function onNextTick() { | ||
defer.resolve(fn.apply(undefined, rootArgs)) | ||
}) | ||
return defer | ||
} | ||
/** | ||
* Returns a promise that will be invoked with the result of a node style | ||
* callback. All args to fn should be given except for the final callback arg | ||
* | ||
* @param {function()} fn | ||
* @param {...} var_args a variable number of arguments | ||
* @return {!Promise} | ||
*/ | ||
function nfcall(fn, var_args) { | ||
// Insert an undefined argument for scope and let bindPromise() do the work. | ||
var args = Array.prototype.slice.call(arguments, 0) | ||
args.splice(1, 0, undefined) | ||
return bindPromise.apply(undefined, args)() | ||
} | ||
/** | ||
* Binds a function to a scope with an optional number of curried arguments. Attaches | ||
* a node style callback as the last argument and returns a promise | ||
* | ||
* @param {function} fn | ||
* @param {function()} fn | ||
* @param {Object} scope | ||
* @param {Object} var_args a variable number of arguments | ||
* @return {Promise} | ||
* @param {...} var_args a variable number of arguments | ||
* @return {function(...)}: !Promise} | ||
*/ | ||
@@ -484,4 +507,5 @@ function bindPromise(fn, scope, var_args) { | ||
, isPromiseLike: isPromiseLike | ||
, nfcall: nfcall | ||
, resolve: resolve | ||
, reject: reject | ||
} |
{ | ||
"name": "kew" | ||
, "description": "a lightweight promise library for node" | ||
, "version": "0.2.2" | ||
, "version": "0.3.0" | ||
, "homepage": "https://github.com/Obvious/kew" | ||
@@ -21,4 +21,4 @@ , "authors": [ | ||
, "devDependencies": { | ||
"q": "0.9.6", | ||
"nodeunit": "0.7.4" | ||
"q": "0.9.7", | ||
"nodeunit": "0.8.1" | ||
} | ||
@@ -25,0 +25,0 @@ , "scripts": { |
@@ -189,4 +189,2 @@ kew: a lightweight (and super fast) promise/deferred framework for node.js | ||
There's only one utility method as of now: | ||
### `.all()` for many things | ||
@@ -238,14 +236,25 @@ | ||
### `.fcall()` for Node.js callbacks | ||
### `.fcall()` for delaying a function invocation until the next tick: | ||
```javascript | ||
// Assume someFn() is a synchronous 2 argument function you want to delay. | ||
Q.fcall(someFn, arg1, arg2) | ||
.then(function (result) { | ||
console.log('someFn(' + arg1 + ', ' + arg2 + ') = ' + result) | ||
}) | ||
``` | ||
``Q.fcall()`` can be used to convert node-style callbacks into promises: | ||
You can also use ``Q.fcall()`` with functions that return promises. | ||
### `.nfcall()` for Node.js callbacks | ||
``Q.nfcall()`` can be used to convert node-style callbacks into promises: | ||
```javascript | ||
Q.fcall(fs.writeFile, '/tmp/myFile', 'content') | ||
.then(function () { | ||
console.log('File written successfully') | ||
}) | ||
.fail(function (err) { | ||
console.log('Failed to write file', err) | ||
}) | ||
Q.nfcall(fs.writeFile, '/tmp/myFile', 'content') | ||
.then(function () { | ||
console.log('File written successfully') | ||
}) | ||
.fail(function (err) { | ||
console.log('Failed to write file', err) | ||
}) | ||
``` | ||
@@ -252,0 +261,0 @@ |
@@ -149,2 +149,13 @@ var Q = require('../kew') | ||
exports.testAllIsPromiseLike = function(test) { | ||
var promises = ['a', originalQ('b')] | ||
Q.all(promises) | ||
.then(function (results) { | ||
test.equal(promises[0], 'a', "First element should be returned") | ||
test.equal(promises[1], 'b', "Second element should be returned") | ||
test.done() | ||
}) | ||
} | ||
// test delay | ||
@@ -166,3 +177,5 @@ exports.testDelay = function (test) { | ||
exports.testFcall = function (test) { | ||
var calledYet = false | ||
var adder = function (a, b) { | ||
calledYet = true | ||
return a + b | ||
@@ -176,4 +189,53 @@ } | ||
}) | ||
test.ok(!calledYet, "fcall() should delay function invocation until next tick") | ||
} | ||
// test fcall works when fn returns a promise | ||
exports.testFcallGivenPromise = function (test) { | ||
var calledYet = false | ||
var eventualAdd = function (a, b) { | ||
calledYet = true | ||
return Q.resolve(a + b) | ||
} | ||
Q.fcall(eventualAdd, 2, 3) | ||
.then(function (val) { | ||
test.equal(val, 5, "Val should be 2 + 3") | ||
test.done() | ||
}) | ||
test.ok(!calledYet, "fcall() should delay function invocation until next tick") | ||
} | ||
// test nfcall, successful case | ||
exports.testNfcall = function (test) { | ||
var nodeStyleEventualAdder = function (a, b, callback) { | ||
setTimeout(function () { | ||
callback(undefined, a + b) | ||
}, 2) | ||
} | ||
Q.nfcall(nodeStyleEventualAdder, 2, 3) | ||
.then(function (val) { | ||
test.equal(val, 5, "Val should be 2 + 3") | ||
test.done() | ||
}) | ||
} | ||
// test nfcall, error case | ||
exports.testNfcallErrors = function (test) { | ||
var err = new Error('fail') | ||
var nodeStyleFailer = function (a, b, callback) { | ||
setTimeout(function() { | ||
callback(err) | ||
}, 2) | ||
} | ||
Q.nfcall(nodeStyleFailer, 2, 3) | ||
.fail(function (e) { | ||
test.equal(e, err, "Promise successfully failed") | ||
test.done() | ||
}) | ||
} | ||
// test binding a callback function with a promise | ||
@@ -180,0 +242,0 @@ exports.testBindPromise = function (test) { |
53327
1176
288