Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added callback-wrapping feature #2

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 18 additions & 3 deletions ERR.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,27 @@

var header = "Async Stacktrace:";

module.exports = function (err, callback)
function ERR(err, callback, asyncStackLine)
{
//there is a error
if(err != null)
{
// determine the new stacktrace line
if (!asyncStackLine)
asyncStackLine = new Error().stack.split("\n")[2];

//if only the callback function is passed
if(typeof err == "function")
{
//wrap callback so ERR() is eventually called w/ the cached stacktrace line
callback = err;
return function(err) {
if (ERR(err, callback, asyncStackLine)) return;
callback.apply(this, arguments);
};
}
//if there is already a stacktrace avaiable
if(err.stack != null)
else if(err.stack != null)
{
//split stack by line
var stackParts = err.stack.split("\n");
Expand All @@ -34,7 +48,6 @@ module.exports = function (err, callback)
}

//add a new stacktrace line
var asyncStackLine = new Error().stack.split("\n")[2];
stackParts.splice(1,0,asyncStackLine);

//join the stacktrace
Expand All @@ -61,3 +74,5 @@ module.exports = function (err, callback)
//return true if an error happend
return err != null;
}

module.exports = ERR;
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,3 +194,23 @@ The parameters of `ERR()` are:
2. `callback` (optional) If the callback is set and an error is passed, it will call the callback with the modified stacktrace. Else it will throw the error

The return value is true if there is an error. Else its false

### Alternate Usage

If all the work that is done in a function is done synchronously before an async call, it can be preferable to simply pass the callback directly to the async call, like this:

```js
function getUsers(db, callback) {
var sql = 'SELECT * FROM users';
db.query(sql, callback);
}
```

`ERR()` can be used in this scenario as well. If it is passed a callback as its first argument, it will wrap the callback, caching the current stacktrace line. When the callback is executed, it will check for an error object and -- if one is exists -- it will add the cached stacktrace line to it:

```js
function getUsers(db, callback) {
var sql = 'SELECT * FROM users';
db.query(sql, ERR(callback));
}
```
35 changes: 35 additions & 0 deletions tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,5 +96,40 @@ vows.describe('ERR function').addBatch({

assert.equal(stackLinesBefore+1, stackLinesAfter);
}
},
'when you call it with a callback as the only argument': {
'it returns a wrapped callback': function() {
var lineNumberRegex = /tests\.js:(\d+):\d+/;

var err = new Error();
var stackLinesBefore = err.stack.split("\n");
var syncLineNumber = lineNumberRegex.exec(stackLinesBefore[1])[1];

var stackLinesAfter;
var asyncLineNumber;
var wrappedCallback = ERR(function(_err) {
stackLinesAfter = _err.stack.split("\n");
asyncLineNumber = lineNumberRegex.exec(stackLinesAfter[1])[1];
});

wrappedCallback(err);
assert.equal(stackLinesBefore.length+3, stackLinesAfter.length);

// because `ERR(...)` is 6 lines after `new Error()` in this test
assert.equal(parseInt(asyncLineNumber), parseInt(syncLineNumber)+6);
}
},
'when you call it with a callback as the only argument then': {
'the wrapping does not interfere with `this` binding or passed args': function() {
var wrappedCallback = ERR(function(_err, arg1, arg2) {
assert.equal(this, "test_this");
assert.equal(err, null);
assert.equal(arg1, "arg1");
assert.equal(arg2, "arg2");
});

var err = null;
wrappedCallback.call("test_this", err, "arg1", "arg2");
}
}
}).run();