laissez-faire
Advanced tools
Comparing version 0.7.1 to 0.7.2
@@ -5,3 +5,3 @@ { | ||
"description": "A Promises/A implementation i.e a \"thenable\"", | ||
"version": "0.7.1", | ||
"version": "0.7.2", | ||
"keywords": ["promise", "async", "future", "control", "flow"], | ||
@@ -8,0 +8,0 @@ "dependencies": {}, |
{ | ||
"name": "laissez-faire", | ||
"version": "0.7.1", | ||
"version": "0.7.2", | ||
"description": "A promise implementation. Simple and fast", | ||
"main": "src/index.js", | ||
"directories": { | ||
"src": "src" | ||
}, | ||
"dependencies": { | ||
"jkroso-emitter": "" | ||
}, | ||
"dependencies": {}, | ||
"devDependencies": { | ||
"bigfile": "", | ||
"bigfile": "*", | ||
"mocha": "*", | ||
"sinon": "*", | ||
"chai": "*", | ||
"promise-tests": "" | ||
"promise-tests": "*" | ||
}, | ||
"scripts": { | ||
"test": "node tests/" | ||
"test": "make test" | ||
}, | ||
@@ -22,0 +17,0 @@ "repository": { |
185
README.md
@@ -296,12 +296,12 @@ # Laissez-faire | ||
- [Promise()](#promise) | ||
- [exports.prepareException()](#exportsprepareexceptionpromisepromisetheerrore) | ||
- [exports.cancelException()](#exportscancelexceptionpromisepromise) | ||
- [exports.rejected](#exportsrejected) | ||
- [exports.fulfilled](#exportsfulfilled) | ||
- [exports.is](#exportsis) | ||
- [proto.then()](#protothendonefunctionfailfunction) | ||
- [proto.end()](#protoenddonefunctionfailfunction) | ||
- [proto.stub](#protostub) | ||
- [proto.resolve()](#protoresolvevalueerror) | ||
- [proto.reject()](#protorejecteerror) | ||
- [proto.assign()](#protoassignxany) | ||
- [proto.fail()](#protofailfnfunction) | ||
- [proto.valueOf()](#protovalueofdonefunctionfailfunction) | ||
- [proto.otherwise()](#protootherwiseerrbackfunction) | ||
- [proto.catch](#protocatch) | ||
- [proto.always()](#protoalwayscallbackfunction) | ||
@@ -311,7 +311,11 @@ - [proto.finish()](#protofinishcallbackfunction) | ||
- [proto.nend()](#protonendcallbackfunction) | ||
- [proto.resolve()](#protoresolvevalueerror) | ||
- [proto.assign()](#protoassignunknownany) | ||
- [proto.reject()](#protorejecteerror) | ||
- [proto.cancel()](#protocancel) | ||
- [proto.yeild()](#protoyeildvalueany) | ||
- [proto.isRejected()](#protoisrejected) | ||
- [proto.isFulfilled()](#protoisfulfilled) | ||
- [proto.proxy()](#protoproxy) | ||
- [exports.rejected](#exportsrejected) | ||
- [exports.fulfilled](#exportsfulfilled) | ||
- [exports.onError()](#exportsonerrorpromisepromisetheerrore) | ||
- [exports.onCatch()](#exportsoncatchpromisepromise) | ||
@@ -326,24 +330,6 @@ ## Promise() | ||
## exports.prepareException(promise:Promise, The:Error e) | ||
## exports.is | ||
Dafualt uncought error handler. It will wait 1 second for you to | ||
handle the error before logging it to the console. Feel free to replace | ||
this function with one you find more useful. Its purely a debugging | ||
feature. Technically promises throw unhandled exceptions. They just sit | ||
around waiting for you to handle them | ||
Ducktype test if an object is a promise | ||
## exports.cancelException(promise:Promise) | ||
Sometimes error handlers may be added after a promise has been rejected. | ||
If you would like to cancel any undhandled exception handling logging | ||
logic you can do so by replaceing this function | ||
## exports.rejected | ||
Helper to quickly create a rejected promise | ||
## exports.fulfilled | ||
Helper to quickly create a completed promise | ||
## proto.then(done:Function, fail:Function) | ||
@@ -354,10 +340,10 @@ | ||
```js | ||
promise.then( | ||
function(value){ | ||
return value | ||
}, | ||
function(error){ | ||
return correction | ||
} | ||
) | ||
promise.then( | ||
function(value){ | ||
return value | ||
}, | ||
function(error){ | ||
return correction | ||
} | ||
) | ||
``` | ||
@@ -371,2 +357,17 @@ | ||
generated by your callbacks | ||
```js | ||
new promise().resolve('unaffected') | ||
.end(function(value) { | ||
value === 'unaffected' // => true | ||
return 'affected' | ||
}) | ||
.then(function(value){ | ||
value === 'unaffected' // => true | ||
return 'affected' | ||
}) | ||
.then(function(value){ | ||
value === 'affected' // => true | ||
}) | ||
``` | ||
@@ -377,2 +378,32 @@ ## proto.stub | ||
## proto.resolve(value:!Error) | ||
Give the promise it's value and propogate it to its pending children | ||
```js | ||
var one = new Promise | ||
, two = one.then() | ||
one.resolve('sandy') | ||
one.then(function(value) {value === 'sandy'}) -> true | ||
two.then(function(value) {value === 'sandy'}) -> true | ||
``` | ||
## proto.reject(e:Error) | ||
Break the promise and propagate the error to subsequent process branches | ||
```js | ||
promise.reject(new Error('Unable to get you your value ...sorry')) | ||
``` | ||
## proto.assign(x:Any) | ||
Delegates to reject if the value is an Error instance otherwise it calls resolve with the value | ||
```js | ||
readFile('/maybe.json', function (err, data) { | ||
promise.assign(err || data) | ||
}) | ||
``` | ||
## proto.fail(fn:Function) | ||
@@ -386,4 +417,9 @@ | ||
attempt to return its resolution synchronously | ||
```js | ||
var promise = new Promise().resolve('bang') | ||
promsie.valueOf() === 'bang' => true | ||
``` | ||
## proto.otherwise(errback:Function) | ||
## proto.catch | ||
@@ -402,3 +438,10 @@ Convenience function for creating a propagating error handler | ||
Allows the use of node style callbacks | ||
Allows the use of node style callbacks while still returning a promise | ||
```js | ||
promise.node(function(err, value) { | ||
if (err) return handleError(err) | ||
return value | ||
}) | ||
``` | ||
@@ -408,30 +451,64 @@ ## proto.nend(callback:Function) | ||
Provides simple access to the promises value via a node style callback | ||
```js | ||
promise.nend(function(err, value) { | ||
if (err) throw err | ||
// do stuff here but don't bother returning anything after | ||
// your done since it will just be ignored use .node(fn) for that | ||
}) | ||
``` | ||
## proto.resolve(value:!Error) | ||
## proto.cancel() | ||
Give the promise it's value and trigger all process branches | ||
Prevent any downstream processes from being invoked once this promise resolves | ||
It will have no effect on completed promises | ||
## proto.assign(unknown:Any) | ||
## proto.yeild(value:Any) | ||
Delegates to resolve or reject, depending on the value given | ||
Create a promise destined to resolve with a given value | ||
```js | ||
function () { | ||
var result = 3 | ||
return promise.then(function(value){ | ||
// something side effect | ||
}).yeild(result) | ||
} | ||
``` | ||
## proto.reject(e:Error) | ||
## proto.isRejected() | ||
Break the promise and propagate the error to subsequent process branches | ||
Did the promise fail | ||
## proto.yeild(value:Any) | ||
## proto.isFulfilled() | ||
Create a promise destined to resolve with a given value | ||
Was the promise successfully completed | ||
## proto.proxy() | ||
Generate a safe interface for a promise | ||
```js | ||
function () { | ||
var result = 3 | ||
return promise.then(function(value){ | ||
// something side effect | ||
}).yeild(result) | ||
} | ||
dangerDanger(promise.proxy()) | ||
``` | ||
## proto.proxy() | ||
## exports.rejected | ||
Generate a safe interface for a promise | ||
Helper to quickly create a rejected promise | ||
## exports.fulfilled | ||
Helper to quickly create a completed promise | ||
## exports.onError(promise:Promise, The:Error e) | ||
Dafualt uncought error handler. It will wait 1 second for you to | ||
handle the error before logging it to the console. Feel free to replace | ||
this function with one you find more useful. Its purely a debugging | ||
feature. Technically promises can't throw unhandled exceptions. They just sit | ||
around waiting for you to handle them | ||
## exports.onCatch(promise:Promise) | ||
Sometimes error handlers may be added after a promise has been rejected. | ||
In such a case you might want to "un-log" the error |
372
src/index.js
@@ -8,66 +8,5 @@ exports = module.exports = Promise | ||
*/ | ||
function Promise () {this.length = 0} | ||
function Promise () {this._len = 0} | ||
/** | ||
* Dafualt uncought error handler. It will wait 1 second for you to | ||
* handle the error before logging it to the console. Feel free to replace | ||
* this function with one you find more useful. Its purely a debugging | ||
* feature. Technically promises throw unhandled exceptions. They just sit | ||
* around waiting for you to handle them | ||
* | ||
* @param {Promise} promise The promise that was rejected without an error handler or child promise | ||
* @param {Error} e The Error instance emitted by the promise | ||
*/ | ||
exports.prepareException = function (promise, e) { | ||
promise._throw = setTimeout(function () { | ||
if (e instanceof Error) { | ||
e.message += ' (Rethrown from rejected promise)' | ||
throw e | ||
} else { | ||
console.warn('Not handled within 1 second: ', e) | ||
} | ||
}, 1000) | ||
} | ||
/** | ||
* Sometimes error handlers may be added after a promise has been rejected. | ||
* If you would like to cancel any undhandled exception handling logging | ||
* logic you can do so by replaceing this function | ||
* | ||
* @param {Promise} promise The promise which previously failed without error handlers | ||
*/ | ||
exports.cancelException = function (promise) { | ||
clearTimeout(promise._throw); | ||
delete promise._throw | ||
} | ||
/** | ||
* Helper to quickly create a rejected promise | ||
* @param {Error} e | ||
* @return {Promise} | ||
*/ | ||
exports.rejected = newRejected | ||
function newRejected (e) { | ||
var p = new Promise | ||
p.reason = e | ||
p.then = rejectedThen | ||
p.end = rejectedEnd | ||
return p | ||
} | ||
/** | ||
* Helper to quickly create a completed promise | ||
* @param {!Error} value can be == null just not an Error | ||
* @return {Promise} | ||
*/ | ||
exports.fulfilled = newFulfilled | ||
function newFulfilled (value) { | ||
var p = new Promise | ||
p.value = value | ||
p.then = resolvedThen | ||
p.end = resolvedEnd | ||
return p | ||
} | ||
/** | ||
* Process the value safely and ensure that what is returned is represented via a new promise | ||
@@ -80,13 +19,10 @@ * | ||
function run (fn, value) { | ||
var result | ||
try { | ||
result = fn(value) | ||
} catch (e) { | ||
return newRejected(e) | ||
} | ||
if (isPromise(result)) { | ||
try { fn = fn(value) } | ||
catch (e) {return newRejected(e) } | ||
if (isPromise(fn)) { | ||
// No need to create a new promise if we already have one | ||
return result === value ? result.then() : result | ||
return fn === value ? fn.then() : fn | ||
} else { | ||
return newFulfilled(result) | ||
return newFulfilled(fn) | ||
} | ||
@@ -120,2 +56,6 @@ } | ||
/** | ||
* Ducktype test if an object is a promise | ||
* @return {Boolean} | ||
*/ | ||
exports.is = isPromise | ||
@@ -126,6 +66,3 @@ function isPromise (item) { | ||
var proto = Promise.prototype = Object.create( | ||
require('jkroso-emitter').prototype, | ||
{constructor:{value:Promise}} | ||
) | ||
var proto = Promise.prototype | ||
// Default states. | ||
@@ -137,10 +74,10 @@ proto.value = proto.reason = null | ||
* | ||
* promise.then( | ||
* function(value){ | ||
* return value | ||
* }, | ||
* function(error){ | ||
* return correction | ||
* } | ||
* ) | ||
* promise.then( | ||
* function(value){ | ||
* return value | ||
* }, | ||
* function(error){ | ||
* return correction | ||
* } | ||
* ) | ||
* | ||
@@ -150,7 +87,6 @@ * @param {Function} done | ||
* @return {Promise} This is a new promise which will be either fulfilled | ||
* or rejected based on the return value of the done/fail params | ||
* unless the previous promise fails to handle an error | ||
*/ | ||
proto.then = function(done, fail) { | ||
var thenPromise | ||
this[this.length++] = (thenPromise = new Promise) | ||
var thenPromise = this[this._len++] = new Promise | ||
thenPromise._success = done | ||
@@ -167,3 +103,3 @@ thenPromise._fail = fail | ||
function rejectedThen (_, fn) { | ||
Promise.cancelException(this) | ||
exports.onCatch(this) | ||
return fn | ||
@@ -179,2 +115,15 @@ ? run(fn, this.reason) | ||
* generated by your callbacks | ||
* | ||
* new promise().resolve('unaffected') | ||
* .end(function(value) { | ||
* value === 'unaffected' // => true | ||
* return 'affected' | ||
* }) | ||
* .then(function(value){ | ||
* value === 'unaffected' // => true | ||
* return 'affected' | ||
* }) | ||
* .then(function(value){ | ||
* value === 'affected' // => true | ||
* }) | ||
* | ||
@@ -187,3 +136,3 @@ * @param {Function} done | ||
// Queue a sudo-promise capable of throwing errors | ||
this[this.length++] = { | ||
this[this._len++] = { | ||
// Handlers are bound to the assignment properties since these aren't run inside a try catch. Having no handlers is fine, the values will just pass straight through to the resolvers. | ||
@@ -199,3 +148,4 @@ resolve: done || noop, | ||
*/ | ||
proto.stub = proto.throw = function (done, fail) {return this.end(done, fail)} | ||
proto.stub = | ||
proto.throw = function (done, fail) {return this.end(done, fail)} | ||
@@ -208,3 +158,3 @@ // Alternative `end` methods for when the state of the promise changes | ||
function rejectedEnd (_, fn) { | ||
Promise.cancelException(this) | ||
exports.onCatch(this) | ||
if (!fn) throw this.reason | ||
@@ -216,2 +166,75 @@ fn(this.reason) | ||
/** | ||
* Give the promise it's value and propogate it to its pending children | ||
* | ||
* var one = new Promise | ||
* , two = one.then() | ||
* one.resolve('sandy') | ||
* one.then(function(value) {value === 'sandy'}) -> true | ||
* two.then(function(value) {value === 'sandy'}) -> true | ||
* | ||
* @param {!Error} value Can be anything other than an Error | ||
* @return {Self} | ||
*/ | ||
proto.resolve = function (value) { | ||
// Change the state | ||
this.value = value | ||
// Change the behavior. In a parallel universe this is just a matter of swapping the prototype. | ||
this.resolve = this.reject = noop | ||
this.then = resolvedThen | ||
this.end = resolvedEnd | ||
// Propagate the value to any queued promises. | ||
var child, i = 0 | ||
while (child = this[i++]) { | ||
if (child._success) propagate(child, child._success, value) | ||
else child.resolve(value) | ||
} | ||
return this | ||
} | ||
/** | ||
* Break the promise and propagate the error to subsequent process branches | ||
* | ||
* promise.reject(new Error('Unable to get you your value ...sorry')) | ||
* | ||
* @param {Error} e The reason for rejection | ||
* @return {Self} | ||
*/ | ||
proto.reject = function (e) { | ||
this.reason = e | ||
this.resolve = this.reject = noop | ||
this.then = rejectedThen | ||
this.end = rejectedEnd | ||
var i = 0 | ||
, child = this[i] | ||
if (child) { | ||
do { | ||
if (child._fail) propagate(child, child._fail, e) | ||
else child.reject(e) | ||
} while (child = this[++i]) | ||
} | ||
else { | ||
exports.onError && exports.onError(this, e) | ||
} | ||
return this | ||
} | ||
/** | ||
* Delegates to reject if the value is an Error instance otherwise it calls resolve with the value | ||
* | ||
* readFile('/maybe.json', function (err, data) { | ||
* promise.assign(err || data) | ||
* }) | ||
* | ||
* @param {Any} x | ||
* @return {self} | ||
*/ | ||
proto.assign = function (x) { | ||
return this[x instanceof Error ? 'reject' : 'resolve'](x) | ||
} | ||
/** | ||
* Create a terminal follow up branch with no success callback | ||
@@ -228,2 +251,5 @@ * @param {Function} fn error handler | ||
* attempt to return its resolution synchronously | ||
* | ||
* var promise = new Promise().resolve('bang') | ||
* promsie.valueOf() === 'bang' => true | ||
* | ||
@@ -248,2 +274,3 @@ * @param {Function} done optional | ||
*/ | ||
proto.catch = | ||
proto.otherwise = function (errback) { | ||
@@ -272,3 +299,8 @@ return this.then(null, errback) | ||
/** | ||
* Allows the use of node style callbacks | ||
* Allows the use of node style callbacks while still returning a promise | ||
* | ||
* promise.node(function(err, value) { | ||
* if (err) return handleError(err) | ||
* return value | ||
* }) | ||
* @param {Function} callback [err, value] | ||
@@ -283,2 +315,9 @@ * @return {Promise} | ||
* Provides simple access to the promises value via a node style callback | ||
* | ||
* promise.nend(function(err, value) { | ||
* if (err) throw err | ||
* // do stuff here but don't bother returning anything after | ||
* // your done since it will just be ignored use .node(fn) for that | ||
* }) | ||
* | ||
* @param {Function} callback [error, value] | ||
@@ -292,69 +331,9 @@ * @return {Self} | ||
/** | ||
* Give the promise it's value and trigger all process branches | ||
* | ||
* @param {!Error} value Can be anything other than an Error | ||
* Prevent any downstream processes from being invoked once this promise resolves | ||
* It will have no effect on completed promises | ||
* @return {Self} | ||
*/ | ||
proto.resolve = function (value) { | ||
// Change the state | ||
this.value = value | ||
// Change the behavior. In a parallel universe this is just a matter of swapping the prototype. | ||
this.resolve = this.reject = noop | ||
this.then = resolvedThen | ||
this.end = resolvedEnd | ||
// Propagate the value to any queued promises. | ||
var child, i = 0 | ||
// Use a forward loop to maintain insertion order | ||
while (child = this[i++]) { | ||
if (child._success) propagate(child, child._success, value) | ||
else child.resolve(value) | ||
} | ||
return this | ||
} | ||
/** | ||
* Delegates to resolve or reject, depending on the value given | ||
* @param {Any} unknown | ||
* @return {self} | ||
*/ | ||
proto.assign = function (unknown) { | ||
return this[unknown instanceof Error ? 'reject' : 'resolve'](unknown) | ||
} | ||
/** | ||
* Break the promise and propagate the error to subsequent process branches | ||
* | ||
* @param {Error} e The reason for rejection | ||
* @return {Self} | ||
*/ | ||
proto.reject = function (e) { | ||
this.reason = e | ||
this.resolve = this.reject = noop | ||
this.then = rejectedThen | ||
this.end = rejectedEnd | ||
var i = 0, child | ||
if (child = this[i]) { | ||
do { | ||
if (child._fail) propagate(child, child._fail, e) | ||
else child.reject(e) | ||
} while (child = this[++i]) | ||
} | ||
else { | ||
// If a promise is rejected without any child promises we might have a genuine error. The following method provides a place for users to access these errors. | ||
Promise.prepareException(this, e) | ||
} | ||
return this | ||
} | ||
/** | ||
* Prevent any downstream processes from being invoked | ||
* @return {Self} | ||
*/ | ||
proto.cancel = function () { | ||
while (this.length--) { | ||
delete this[this.length] | ||
while (this._len--) { | ||
delete this[this._len] | ||
} | ||
@@ -367,8 +346,8 @@ return this | ||
* | ||
* function () { | ||
* var result = 3 | ||
* return promise.then(function(value){ | ||
* // something side effect | ||
* }).yeild(result) | ||
* } | ||
* function () { | ||
* var result = 3 | ||
* return promise.then(function(value){ | ||
* // something side effect | ||
* }).yeild(result) | ||
* } | ||
* | ||
@@ -382,5 +361,14 @@ * @param {Any} value | ||
/** | ||
* Did the promise fail | ||
* @return {Boolean} | ||
*/ | ||
proto.isRejected = function () { | ||
return this.then === rejectedThen | ||
} | ||
/** | ||
* Was the promise successfully completed | ||
* @return {Boolean} | ||
*/ | ||
proto.isFulfilled = function () { | ||
@@ -392,2 +380,4 @@ return this.then === resolvedThen | ||
* Generate a safe interface for a promise | ||
* | ||
* dangerDanger(promise.proxy()) | ||
* | ||
@@ -405,1 +395,61 @@ * @return {Object} The promise with minimal interface | ||
function noop () {} | ||
/** | ||
* Helper to quickly create a rejected promise | ||
* @param {Error} e | ||
* @return {Promise} | ||
*/ | ||
exports.rejected = newRejected | ||
function newRejected (e) { | ||
var p = new Promise | ||
p.reason = e | ||
p.then = rejectedThen | ||
p.end = rejectedEnd | ||
return p | ||
} | ||
/** | ||
* Helper to quickly create a completed promise | ||
* @param {!Error} value can be == null just not an Error | ||
* @return {Promise} | ||
*/ | ||
exports.fulfilled = newFulfilled | ||
function newFulfilled (value) { | ||
var p = new Promise | ||
p.value = value | ||
p.then = resolvedThen | ||
p.end = resolvedEnd | ||
return p | ||
} | ||
/** | ||
* Dafualt uncought error handler. It will wait 1 second for you to | ||
* handle the error before logging it to the console. Feel free to replace | ||
* this function with one you find more useful. Its purely a debugging | ||
* feature. Technically promises can't throw unhandled exceptions. They just sit | ||
* around waiting for you to handle them | ||
* | ||
* @param {Promise} promise The promise that was rejected without an error handler or child promise | ||
* @param {Error} e The Error instance emitted by the promise | ||
*/ | ||
exports.onError = function (promise, e) { | ||
promise._throw = setTimeout(function () { | ||
if (e instanceof Error) { | ||
e.message += ' (Rethrown from rejected promise)' | ||
throw e | ||
} else { | ||
console.warn('Not handled within 1 second: ', e) | ||
} | ||
}, 1000) | ||
} | ||
/** | ||
* Sometimes error handlers may be added after a promise has been rejected. | ||
* In such a case you might want to "un-log" the error | ||
* | ||
* @param {Promise} promise The promise which previously failed without error handlers | ||
*/ | ||
exports.onCatch = function (promise) { | ||
clearTimeout(promise._throw); | ||
delete promise._throw | ||
} |
Sorry, the diff of this file is not supported yet
Wildcard dependency
QualityPackage has a dependency with a floating version range. This can cause issues if the dependency publishes a new major version.
Found 1 instance in 1 package
51250
0
444
1
506
- Removedjkroso-emitter@
- Removedjkroso-emitter@0.4.0(transitive)