Skip to content

Instantly share code, notes, and snippets.

@jimmyjacobson
Last active December 27, 2021 20:49
Show Gist options
  • Select an option

  • Save jimmyjacobson/f98ffe22d3259fe1062d to your computer and use it in GitHub Desktop.

Select an option

Save jimmyjacobson/f98ffe22d3259fe1062d to your computer and use it in GitHub Desktop.
A String is not an Error

A String is not an Error

Why Error Handling?

  • Default behavior for programs is to terminate on an error, or enter the debugger
  • Terrible user experience

Why Handle Errors?

  • Gracefully Handle Errors (retry connections, re-prompt for user input, etc)
  • Non Local Control Flow (Display error messages and screens)

This is not a Javascript Error

  • “Ooops, something went wrong"
  • callback(“Oops something went wrong”);
function myFunction (callback) {
  doSomethingAsync(function () {
    // …
    if (somethingWrong) {
      callback('This is my error')
    } else {
      callback(null, …);
    }
  });
} 

This is a Javascript Error

  • new Error(“Oops something went wrong”);
  • callback(new Error(“Oops something went wrong”);
function myFunction (callback) {
  doSomethingAsync(function () {
    // …
    if (somethingWrong) {
      callback(new Error('This is my error'))
    } else {
      callback(null, …);
    }
  });
}

A Javascript Error includes a Stack Trace (usually)

  • see where the error happened in your code with line numbers
  • OMG STACK TRACES
// error.js
var err = new Error();
console.log(typeof err.stack);
console.log(err.stack);
∞ node error.js
string
Error
    at Object.<anonymous> (/private/tmp/error.js:2:11)
    at Module._compile (module.js:411:26)
    at Object..js (module.js:417:10)
    at Module.load (module.js:343:31)
    at Function._load (module.js:302:12)
    at Array.0 (module.js:430:10)
    at EventEmitter._tickCallback (node.js:126:26)

Custom Errors

  • Define your own error types
  • Handle with instanceof
function MongooseError (msg) {
  Error.call(this);
  Error.captureStackTrace(this, arguments.callee);
  this.message = msg;
  this.name = 'MongooseError';
};

MongooseError.prototype.__proto__ = Error.prototype;

Advanced Manuvers

function NotFound(msg) {
  Error.call(this, msg);
  Error.captureStackTrace(this, arguments.callee);
  this.name = 'NotFound';
  this.message = msg;
}
NotFound.prototype.__proto__ = Error.prototype;
exports.NotFound = NotFound;
function errorHandler (err, req, res, next) {
  if (err instanceof NotFound) {
    res.status(404);
    return res.render('errors/404', {
      config: config,
      url: req.url,
      identifier: 'error'
    });
  } 

  res.status(500);
  return res.render('errors/500', {
    config: config,
    url: req.url,
    identifier: 'error'
  });

References

http://www.devthought.com/2011/12/22/a-string-is-not-an-error/ http://eloquentjavascript.net/1st_edition/chapter5.html

@tgeene
Copy link
Copy Markdown

tgeene commented Feb 18, 2015

Hi Jimmy,

I was at the meet up this evening. I tried to follow as best as I could, but I ran into issues trying to make my own example with a use case. Can you please look over my code an tell me what I am doing wrong?

var err = new Error();

function TestingError(msg) {
  Error.call(this, msg);
  Error.captureStackTrace(this, arguments.callee);
  this.name = 'TestingError';
  this.message = msg;
}
TestingError.prototype.__proto__ = Error.prototype;

function errorHandler(err) {
  if(err instanceof TestingError) {
    return "An error has occurred.";
  }
}

try {
  throw TestingError('error here');
}
catch (e) {
  errorHandler(e);
}
finally {
  console.log('testing');
}

Thanks in advance.

@jimmyjacobson
Copy link
Copy Markdown
Author

Trevor,

Your code was 99.999% of the way there. You were just missing the "new" keyword between "throw" and "Testing Error".

var err = new Error();

function TestingError(msg) {
    Error.call(this, msg);
    Error.captureStackTrace(this, arguments.callee);
    this.name = 'TestingError';
    this.message = msg;
}
TestingError.prototype.__proto__ = Error.prototype;

function errorHandler(err) {
    console.log(err);
    if (err instanceof TestingError) {
        return "Testing Error Occurred";
    } else {
        return "Undefined Error Occurred";
    }
}

try {
    throw new TestingError('error here');
} catch (e) {
    alert(errorHandler(e));
} finally {
    alert('Done Testing');
}

I threw the code into a fiddle and changed console to alert so the result is more obvious. I also tweaked the error handler a little but the "new" keyword is the only thing that was causing your code not to execute as you expected.

http://jsfiddle.net/s846na6z/

@tgeene
Copy link
Copy Markdown

tgeene commented Feb 18, 2015

Thank you so much!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment