admin管理员组

文章数量:1134554

How would you implement different types of errors, so you'd be able to catch specific ones and let others bubble up..?

One way to achieve this is to modify the prototype of the Error object:

Error.prototype.sender = "";


function throwSpecificError()
{
    var e = new Error();

    e.sender = "specific";

    throw e;
}

Catch specific error:

try
{
    throwSpecificError();
}

catch (e)
{
    if (e.sender !== "specific") throw e;

    // handle specific error
}


Have you guys got any alternatives?

How would you implement different types of errors, so you'd be able to catch specific ones and let others bubble up..?

One way to achieve this is to modify the prototype of the Error object:

Error.prototype.sender = "";


function throwSpecificError()
{
    var e = new Error();

    e.sender = "specific";

    throw e;
}

Catch specific error:

try
{
    throwSpecificError();
}

catch (e)
{
    if (e.sender !== "specific") throw e;

    // handle specific error
}


Have you guys got any alternatives?

Share Improve this question edited Sep 16, 2009 at 16:23 cllpse asked Sep 16, 2009 at 15:00 cllpsecllpse 21.7k37 gold badges133 silver badges170 bronze badges
Add a comment  | 

8 Answers 8

Reset to default 259

To create custom exceptions, you can inherit from the Error object:

function SpecificError () {

}

SpecificError.prototype = new Error();

// ...
try {
  throw new SpecificError;
} catch (e) {
  if (e instanceof SpecificError) {
   // specific error
  } else {
    throw e; // let others bubble up
  }
}

A minimalistic approach, without inheriting from Error, could be throwing a simple object having a name and a message properties:

function throwSpecificError() {
  throw {
    name: 'SpecificError',
    message: 'SpecificError occurred!'
  };
}


// ...
try {
  throwSpecificError();
} catch (e) {
  if (e.name == 'SpecificError') {
   // specific error
  } else {
    throw e; // let others bubble up
  }
}

As noted in the comments below this is Mozilla specific, but you can use 'conditional catch' blocks. e.g.:

try {
  ...
  throwSpecificError();
  ...
}
catch (e if e.sender === "specific") {
  specificHandler(e);
}
catch (e if e.sender === "unspecific") {
  unspecificHandler(e);
}
catch (e) {
  // don't know what to do
  throw e;
} 

This gives something more akin to typed exception handling used in Java, at least syntactically.

There is unfortunately no "official" way to achieve this basic functionality in Javascript. I'll share the three most common solutions I've seen in different packages, and how to implement them in modern Javascript (es6+), along with some of their pros and cons.

1. Subclass the Error class

Subclassing an instance of "Error" has become much easier in es6. Just do the following:

class FileNotFoundException extends Error {
  constructor(message) {
    super(message);
    // Not required, but makes uncaught error messages nicer.
    this.name = 'FileNotFoundException';
  }
}

Complete example:

class FileNotFoundException extends Error {
  constructor(message) {
    super(message);
    // Not required, but makes uncaught error messages nicer.
    this.name = 'FileNotFoundException';
  }
}

// Example usage

function readFile(path) {
  throw new FileNotFoundException(`The file ${path} was not found`);
}

try {
  readFile('./example.txt');
} catch (err) {
  if (err instanceof FileNotFoundException) {
    // Handle the custom exception
    console.log(`Could not find the file. Reason: ${err.message}`);
  } else {
    // Rethrow it - we don't know how to handle it
    // The stacktrace won't be changed, because
    // that information is attached to the error
    // object when it's first constructed.
    throw err;
  }
}

If you don't like setting this.name to a hard-coded string, you can instead set it to this.constructor.name, which will give the name of your class. This has the advantage that any subclasses of your custom exception wouldn't need to also update this.name, as this.constructor.name will be the name of the subclass.

Subclassed exceptions have the advantage that they can provide better editor support (such as autocomplete) compared to some of the alternative solutions. You can easily add custom behavior to a specific exception type, such as additional functions, alternative constructor parameters, etc. It also tends to be easier to support typescript when providing custom behavior or data.

There's a lot of discussion about how to properly subclass Error out there. For example, the above solution might not work if you're using a transpiler. Some recommend using the platform-specific captureStackTrace() if it's available (I didn't notice any difference in the error when I used it though - maybe it's not as relevant anymore

本文标签: Handling specific errors in JavaScript (think exceptions)Stack Overflow