Comparing version 0.0.3 to 0.0.5
@@ -6,2 +6,5 @@ var fs = require('fs'), | ||
var onResult = outcome.error(function(err) { | ||
@@ -11,2 +14,4 @@ console.log(err); | ||
console.log(result) | ||
}).callback(function(err, result) { | ||
console.log("CALLBACK") | ||
}); | ||
@@ -16,7 +21,20 @@ | ||
var onResult2 = onResult.copy().success(function(result) { | ||
var onResult2 = onResult.success(function(result) { | ||
console.log("RESULT") | ||
}).done(function(err, result) { | ||
console.log('DONE') | ||
}); | ||
var onResult3 = outcome({ | ||
error: function() { | ||
console.log("ERR") | ||
}, | ||
success: function() { | ||
console.log("SUCC") | ||
}, | ||
callback: function(err, result) { | ||
console.log("CB") | ||
} | ||
}) | ||
@@ -27,2 +45,3 @@ | ||
fs.stat('s'+__filename, onResult2); | ||
fs.stat('s'+__filename, onResult3) | ||
118
lib/index.js
var EventEmitter = require('events').EventEmitter, | ||
//used for dispatching unhandledError messages | ||
globalEmitter = new EventEmitter(), | ||
globalEmitter = new EventEmitter(); | ||
_ = require('underscore'); | ||
var Chain = function(listeners) { | ||
var Chain = function(listeners, parent) { | ||
if(!listeners) listeners = { }; | ||
var doneListeners = [], | ||
self = function() { | ||
var fn = function() { | ||
var args = Array.apply(null, arguments), orgArgs = arguments; | ||
if(listeners.callback) { | ||
listeners.callback.apply(this, args); | ||
} | ||
if(listeners.handle) { | ||
listeners.handle.apply(listeners, args); | ||
} else { | ||
//error should always be first args | ||
err = args.shift(); | ||
//on error | ||
if(err) { | ||
//if there is an error, and a result is *not* present, then continue | ||
if(err && !args[0]) { | ||
listeners.error.call(this, err); | ||
listeners.error(err); | ||
} else | ||
if(listeners.success) { | ||
listeners.success.apply(this, args); | ||
} else { | ||
listeners.success.apply(null, args); | ||
} | ||
} | ||
doneListeners.forEach(function(fn) { | ||
fn.apply(null, orgArgs); | ||
}); | ||
} | ||
}; | ||
self.listeners = listeners; | ||
fn.listeners = listeners; | ||
self.done = function(fn) { | ||
//DEPRECATED | ||
fn.done = function(fn) { | ||
doneListeners.push(fn); | ||
return self; | ||
return fn.callback(fn); | ||
} | ||
fn.handle = function(value) { | ||
return _copy({ handle: value }); | ||
self.copy = function(childListeners) { | ||
} | ||
return Chain(_.extend({}, listeners, childListeners || {}), self); | ||
fn.callback = function(value) { | ||
return _copy({ callback: value }); | ||
} | ||
self.handle = function(fn) { | ||
fn.success = function(value) { | ||
return _copy({ success: value }); | ||
listeners.handle = fn; | ||
return self; | ||
} | ||
fn.error = function(value) { | ||
self.success = function(fn) { | ||
listeners.success = fn || function(){}; | ||
return _copy({ error: value }); | ||
return self; | ||
} | ||
self.error = function(fn) { | ||
listeners.error = fn || function(err) { | ||
//error does not exist? set the default which throws one | ||
if(!listeners.error) { | ||
listeners.error = function(err) { | ||
//no error callback? check of unhandled error is present, or throw | ||
if(!globalEmitter.emit('unhandledError', err)) throw err; | ||
if(!globalEmitter.emit('unhandledError', err) && !listeners.callback) throw err; | ||
} | ||
} | ||
function _copy(childListeners) { | ||
//copy these listeners to a new chain | ||
for(var type in listeners) { | ||
return self; | ||
}; | ||
if(childListeners[type]) continue; | ||
self.error(listeners.error); | ||
childListeners[type] = listeners[type]; | ||
return self; | ||
} | ||
} | ||
return Chain(childListeners); | ||
module.exports = function(listeners) { | ||
return Chain(listeners); | ||
} | ||
return fn; | ||
} | ||
//ability to listen for unhandledError | ||
module.exports.on = function() { | ||
module.exports = function(listeners) { | ||
globalEmitter.on.apply(globalEmitter, arguments); | ||
return Chain(listeners); | ||
} | ||
module.exports.chain = Chain; | ||
//bleh this could be better. Need to copy the chain functions to the module.exports var | ||
var chain = Chain(); | ||
//copy the obj keys to module.exports | ||
Object.keys(chain).forEach(function(prop) { | ||
//on call of error, success, callback - make a new chain | ||
module.exports[prop] = function() { | ||
@@ -115,6 +133,14 @@ | ||
} | ||
}) | ||
}); | ||
//running online? | ||
if(typeof window != 'undefined') { | ||
window.outcome = module.exports; | ||
} | ||
{ | ||
"name": "outcome", | ||
"description": "Better Result Handling", | ||
"version": "0.0.3", | ||
"repository": {}, | ||
"engines": {}, | ||
"dependencies": { | ||
"underscore": "*" | ||
}, | ||
"devDependencies": {}, | ||
"main": "./lib/index.js" | ||
"name": "outcome", | ||
"description": "DRY error handling", | ||
"author": "Craig Condon", | ||
"repository": { | ||
"type": "git", | ||
"url": "git://github.com/crcn/outcome.js.git" | ||
}, | ||
"repository": {}, | ||
"version": "0.0.5", | ||
"engines": {}, | ||
"dependencies": {}, | ||
"devDependencies": {}, | ||
"main": "./lib/index.js" | ||
} |
201
README.md
### Old Way | ||
Outcome.js is a simple flow-control library which wraps your `.callback(err, result)` functions. | ||
### Motiviation | ||
- Write less code for handling errors. | ||
- Easier to maintain. | ||
- Keep error handling code separate. | ||
### Basic Example | ||
Here's the traditional method of handling errors: | ||
```javascript | ||
var fs = require('fs'); | ||
fs.stat('some/file.js', function(err, data) { | ||
function doSomething(path, callback) { | ||
fs.realpath(path, onRealPath); | ||
function onRealPath(err, path) { | ||
if(err) return callback(err); | ||
fs.lstat(path, onStat); | ||
} | ||
function onStat(err, stats) { | ||
if(err) return callback(err); | ||
callback(err, stats); | ||
} | ||
} | ||
doSomething('/path/to/something', function(err, result) { | ||
//inline with result handling - yuck | ||
if(err) { | ||
//do stuff, or throw | ||
//do something with error | ||
return; | ||
} | ||
//do success stuff | ||
}); | ||
//do something with result | ||
}) | ||
``` | ||
## Outcome API | ||
The outcome.js way: | ||
```javascript | ||
### .outcome(listeners) | ||
var fs = require('fs'), | ||
outcome = require('outcome'); | ||
- `listeners` - success, or error | ||
function doSomething(path, callback) { | ||
```javascript | ||
//wrap the callback around an error handler so any errors in *this* function | ||
//bubble back up to the callback - I'm lazy and I don't wanna write this stuff... | ||
var on = outcome.error(callback); | ||
//on success, call onRealPath. Any errors caught will be sent back | ||
//automatically | ||
fs.realpath(path, on.success(onRealPath)); | ||
var resultHandler = outcome.error(function(err) { | ||
console.log(err); | ||
}); | ||
function onRealPath(path) { | ||
//success | ||
fs.stat(__filename, resultHandler.copy().success(function(data) { | ||
//do stuff | ||
//ONLY call onStat if we've successfuly grabbed the file stats | ||
fs.lstat(path, on.success(onStat)); | ||
} | ||
function onStat(stats) { | ||
//no errors, so send a response back | ||
callback(null, stats); | ||
} | ||
} | ||
var on = outcome.error(function(error) { | ||
//do something with error | ||
})); | ||
//success | ||
fs.stat(__filename, resultHandler.copy().success(function(data) { | ||
//do stuff | ||
})); | ||
doSomething('/path/to/something', on.success(function(response) { | ||
//do something with result | ||
})); | ||
//this fails - error is passed to above func | ||
fs.stat('s'+__filename, resultHandler.copy().success(function(data) { | ||
//do stuff | ||
})); | ||
``` | ||
## API | ||
```` | ||
### outcome(listeners) | ||
Or | ||
- `listeners` - Object of listeners you want to attach to outcome. | ||
```javascript | ||
var onOutcome = outcome({ | ||
success: function() { | ||
console.log("SUCCESS"); | ||
var onResult = outcome({ | ||
//called when an error is caught | ||
error: function(error) { | ||
}, | ||
error: function() { | ||
console.log("ERROR"); | ||
//called when an error is NOT present | ||
success: function(result, thirdParam) { | ||
}, | ||
//called back when an error, or result is present | ||
callback: function(err, result, thirdParam) { | ||
} | ||
}); | ||
}) | ||
fs.stat(__filename, onOutcome); | ||
``` | ||
As shown in the example above, you can also wrap-around an existing callback: | ||
```javascript | ||
var onResult = outcome.error(function(error) { | ||
}). | ||
success(function(result, thirdParam) { | ||
}). | ||
callback(function(error, result, thirdParam) { | ||
}); | ||
``` | ||
@@ -77,15 +143,16 @@ | ||
//fails | ||
fs.stat('s'+__filename, outcome({ | ||
success: function(){} | ||
})); | ||
fs.stat('s'+__filename, outcome.success(function() { | ||
}); | ||
``` | ||
### .copy() | ||
Copies the current call chain. Useful for using one error handler, and many result handlers. See first example. | ||
### .done() | ||
### .callback() | ||
Called when on error/success. `Same as function(err, data) { }` | ||
Here's a redundant example: | ||
```javascript | ||
@@ -97,5 +164,5 @@ | ||
//handle result | ||
}.done(function(err, result) { | ||
//called on fn complete | ||
}); | ||
}.callback(function(err, result) { | ||
//called on fn complete regardless if there's an error, or success | ||
})); | ||
@@ -106,10 +173,10 @@ ``` | ||
Called on success | ||
Called on Success. | ||
```javascript | ||
var onOutcome = outcome.success(function(data) { | ||
var onOutcome = outcome.success(function(data, anotherParam, andAnotherParam) { | ||
//handle success data | ||
}); | ||
onOutcome(null, "success!"); | ||
onOutcome(null, "success!", "more data!", "more results.."); | ||
``` | ||
@@ -119,3 +186,3 @@ | ||
Called on error | ||
Called on error. | ||
@@ -128,3 +195,3 @@ ```javascript | ||
onOutcome(new Error("ERR")); | ||
onOutcome(new Error("something went wrong...")); | ||
``` | ||
@@ -146,1 +213,39 @@ | ||
## CoffeeScript Example | ||
```coffeescript | ||
outcome = require "outcome" | ||
doSomething(path, callback) -> | ||
on = outcome.error callback | ||
# first get the realpath | ||
fs.realpath path, on.success onRealPath | ||
# on real path, get stats | ||
onRealPath(path) -> fs.lstat path, on.success onStat | ||
# on stat, finish | ||
onStat(stats) -> callback null, stats | ||
# call do something | ||
doSomething '/path/to/something', outcome | ||
success: (statis) -> | ||
# do something | ||
error: (error) -> | ||
# do something else | ||
``` | ||
### Note | ||
Calling `.error()`, `.success()`, `.callback()` generates a new function which copies the previous listeners. | ||
Checkout [fs-test](outcome.js/blob/master/examples/fs-test.js) in the [examples](outcome.js/blog/master/examples) folder. |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No contributors or author data
MaintenancePackage does not specify a list of contributors or an author in package.json.
Found 1 instance in 1 package
No License Found
License(Experimental) License information could not be found.
Found 1 instance in 1 package
54712
0
13
0
685
2
0
246
3
15
- Removedunderscore@*
- Removedunderscore@1.13.7(transitive)