Permalink
Browse files

Made the callback to a method hook the first place to look for an err…

…or handler. Otherwise, the fallback is now the error handler you set up in #hook or lazy #pre. After these two options, the final fallback is throwing the Error.
  • Loading branch information...
1 parent 1f90ff1 commit 8feb4d3d48b6ed1d2f5c74afefb32331c53e2ce8 @bnoguchi committed Jun 14, 2011
Showing with 64 additions and 30 deletions.
  1. +26 −28 README.md
  2. +1 −1 hooks.js
  3. +37 −1 test.js
View
@@ -24,6 +24,7 @@ methods.
## Example
We can use `hooks` to add validation and background jobs in the following way:
+
var hooks = require('hooks')
, Document = require('./path/to/some/document/constructor');
@@ -100,7 +101,7 @@ We structure pres and posts as middleware to give you maximum flexibility:
As soon as one pre finishes executing, the next one will be invoked, and so on.
## Error Handling
-You can define an error handler by passing a 2nd function as the 3rd argument to `hook`:
+You can define a default error handler by passing a 2nd function as the 3rd argument to `hook`:
Document.hook('set', function (path, val) {
this[path] = val;
}, function (err) {
@@ -113,35 +114,28 @@ Then, we can pass errors to this handler from a pre or post middleware function:
next(new Error());
});
-Alternatively, you do not need to provide a distinct error handler. There are 2 default fallbacks.
+If you do not set up a default handler, then `hooks` makes the default handler that just throws the `Error`.
-1. If the main method that you are surrounding with pre and post middleware expects its last argument to be a function
- with callback signature `function (error, ...)`, then that callback becomes the error handler, by not specifying an
- error handler.
-
- Document.hook('save', function (callback) {
- // Save logic goes here
- ...
- });
-
- var doc = new Document();
- doc.save( function (err, saved) {
- // We can pass err via `next` in any of our pre or post middleware functions
- if (err) console.error(err);
-
- // Rest of callback logic follows ...
- });
-
-2. If the main method that you are surrounding with pre and post middleware expects a potential error as one of its arguments,
- then you can make the main method also be the error handler, by not specifying an error handler
- as the 3rd argument to `hook`:
+The default error handler can be over-rided on a per method invocation basis.
+
+If the main method that you are surrounding with pre and post middleware expects its last argument to be a function
+with callback signature `function (error, ...)`, then that callback becomes the error handler, over-riding the default
+error handler you may have set up.
- Document.hook('save', function (err, callback) {
- // We can pass err via `next` in any of our pre or post middleware functions
- if (err) console.error(err);
- // Save logic goes here
- ...
- });
+```javascript
+Document.hook('save', function (callback) {
+ // Save logic goes here
+ ...
+});
+
+var doc = new Document();
+doc.save( function (err, saved) {
+ // We can pass err via `next` in any of our pre or post middleware functions
+ if (err) console.error(err);
+
+ // Rest of callback logic follows ...
+});
+```
## Mutating Arguments via Middleware
`pre` and `post` middleware can also accept the intended arguments for the method
@@ -152,6 +146,7 @@ the main method itself.
As a simple example, let's define a method `set` that just sets a key, value pair.
If we want to namespace the key, we can do so by adding a `pre` middleware hook
that runs before `set`, alters the arguments by namespacing the `key` argument, and passes them onto `set`:
+
Document.hook('set', function (key, val) {
this[key] = val;
});
@@ -168,6 +163,7 @@ As you can see above, we pass arguments via `next`.
If you are not mutating the arguments, then you can pass zero arguments
to `next`, and the next middleware function will still have access
to the arguments.
+
Document.hook('set', function (key, val) {
this[key] = val;
});
@@ -181,6 +177,7 @@ to the arguments.
});
Finally, you can add arguments that downstream middleware can also see:
+
// Note that in the definition of `set`, there is no 3rd argument, options
Document.hook('set', function (key, val) {
// But...
@@ -287,6 +284,7 @@ So what's happening is that:
## Removing Pres
You can remove a particular pre associated with a hook:
+
Document.pre('set', someFn);
Document.removePre('set', someFn);
View
@@ -88,9 +88,9 @@ module.exports = {
}
}
function handleError (err) {
- if (errorCb) return errorCb(err);
if ('function' == typeof lastArg)
return lastArg(err);
+ if (errorCb) return errorCb.call(self, err);
throw err;
}
return _next.apply(this, arguments);
View
38 test.js
@@ -208,6 +208,42 @@ module.exports = {
counter.should.equal(1);
should.deepEqual(undefined, a.value);
},
+ 'should fall back second to the default error handler if specified': function () {
+ var A = function () {};
+ _.extend(A, hooks);
+ var counter = 0;
+ A.hook('save', function (callback) {
+ this.value = 1;
+ }, function (err) {
+ if (err instanceof Error) counter++;
+ });
+ A.pre('save', true, function (next, done) {
+ next(new Error());
+ });
+ var a = new A();
+ a.save();
+ counter.should.equal(1);
+ should.deepEqual(undefined, a.value);
+ },
+ 'fallback default error handler should scope to the object': function () {
+ var A = function () {
+ this.counter = 0;
+ };
+ _.extend(A, hooks);
+ var counter = 0;
+ A.hook('save', function (callback) {
+ this.value = 1;
+ }, function (err) {
+ if (err instanceof Error) this.counter++;
+ });
+ A.pre('save', true, function (next, done) {
+ next(new Error());
+ });
+ var a = new A();
+ a.save();
+ a.counter.should.equal(1);
+ should.deepEqual(undefined, a.value);
+ },
'should fall back last to throwing the error': function () {
var A = function () {};
_.extend(A, hooks);
@@ -597,7 +633,7 @@ module.exports = {
a.preValue.should.equal(2);
},
- '#pre lazily making a method hookable should be able to provide an errorHandler as the last argument': function () {
+ '#pre lazily making a method hookable should be able to provide a default errorHandler as the last argument': function () {
var A = function () {};
var preValue = "";
_.extend(A, hooks);

0 comments on commit 8feb4d3

Please sign in to comment.