Skip to content

Instantly share code, notes, and snippets.

@jimmyjacobson
Last active December 27, 2021 20:49
Show Gist options
  • Save jimmyjacobson/f98ffe22d3259fe1062d to your computer and use it in GitHub Desktop.
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

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
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

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