- Error handling can be very redundant.
- I find it cleaner when error / success code are kept separate.
- It becomes an easy habit not to handle errors, or write code which handles errors poorly.
var fs = require('fs');
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);
}
}
var fs = require('fs'),
outcome = require('outcome');
function doSomething(path, callback) {
//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));
function onRealPath(path) {
//ONLY call onStat if we're successfuly grabbed the file stats
fs.lstat(path, on.success(onStat));
}
function onStat(stats) {
//no errors, so send a response back
callback(null, stats);
}
}
listeners
- Object of listeners you want to attach to outcome.
var onResult = outcome({
//called when an error is caught
error: function(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) {
}
})
As shown in the example above, you can also wrap-around an existing callback:
var onResult = outcome.error(function(error) {
}).
success(function(result, thirdParam) {
}).
callback(function(error, result, thirdParam) {
});
Here's how I like to do it:
function doSomething(ops, callback) {
//the FIRST part of the function wraps around the callback for errors
var on = outcome.error(callback);
//the "on" var is then passed to other async functions only to handle results.
//Errors are ALWAYS bubbled up to the original caller, or handled wherever it
//seems logical.
//example:
fs.stat(ops.path, on.success(onStatSuccess));
//The result handler. No error handling here!
function onStatSuccess(stats) {
}
}
By default, any unhandled errors are thrown. To get around this, you'll need to listen for an unhandledError
:
outcome.on('unhandledError', function(error) {
//report bugs here..., then throw again.
});
//fails
fs.stat('s'+__filename, outcome.success(function() {
});
Called when on error/success. Same as function(err, data) { }
Here's a redundant example:
fs.stat(__filename, outcome.error(function(err) {
//handle error
}).success(function(data) {
//handle result
}.callback(function(err, result) {
//called on fn complete regardless if there's an error, or success
}));
Called on success
var onOutcome = outcome.success(function(data, anotherParam, andAnotherParam) {
//handle success data
});
onOutcome(null, "success!", "more data!", "more results..");
Called on error
var onOutcome = outcome.error(function(err) {
});
onOutcome(new Error("something went wrong..."));
Custom response handler
outcome.handle(function(response) {
if(response.errors) this.error(response);
if(response.data) this.success(response);
});