Custom Error Handling
Error Handling: Custom Errors
What are the benefits of inheriting from the Error object vs. simply using the throw statement?
View Answer:
Interview Response: Because JavaScript allows us to use a throw with any parameter, our error classes do not need to derive from Error. However, we may use obj instanceof Error to identify and track error objects if we inherit. As a result, it is preferable to inherit from it. Our errors automatically build a hierarchy as the program evolves, and ValidationError, for example, may derive from the Error Object, and so forth.
Code Example: Custom ValidationError that extends the built-in Error Object
class ValidationError extends Error {
constructor(message) {
super(message);
this.name = 'ValidationError';
}
}
// Usage
function readUser(json) {
let user = JSON.parse(json);
if (!user.age) {
throw new ValidationError('No field: age');
}
if (!user.name) {
throw new ValidationError('No field: name');
}
return user;
}
// Working example with try..catch
try {
let user = readUser('{ "age": 25 }');
} catch (err) {
if (err instanceof ValidationError) {
alert('Invalid data: ' + err.message); // Invalid data: No field: name
} else if (err instanceof SyntaxError) {
// (*)
alert('JSON Syntax Error: ' + err.message);
} else {
throw err; // unknown error, rethrow it (**)
}
}
Is there any difference in inheritance when inheriting/extending from the Error class object and regular class inheritance?
View Answer:
Interview Response: No, the same rules apply; you can only inherit from one base class using the extends keyword. In class declarations or expressions, we can use the extends keyword to build a class that is a child of another class.
How would you extend beyond the initial inheritance of the Error object?
View Answer:
Interview Response: If it is necessary to extend beyond a primary child class that has already extended the built-in Error Object. It would be best to inherit/extend from the child class to access the base class.
Code Example: Extending beyond the initial base/child inheritance
// Initial Inheritance from the base Error Object
class ValidationError extends Error {
constructor(message) {
super(message);
this.name = "ValidationError";
}
}
// Secondary Inheritance from the ValidationError Class
class PropertyRequiredError extends ValidationError {
constructor(property) {
super("No property: " + property);
this.name = "PropertyRequiredError";
this.property = property;
}
}
// Usage
function readUser(json) {
let user = JSON.parse(json);
if (!user.age) {
throw new PropertyRequiredError("age");
}
if (!user.name) {
throw new PropertyRequiredError("name");
}
return user;
}
// Working example with try..catch
try {
let user = readUser('{ "age": 25 }');
} catch (err) {
if (err instanceof ValidationError) {
alert("Invalid data: " + err.message); // Invalid data: No property: name
alert(err.name); // PropertyRequiredError
alert(err.property); // name
} else if (err instanceof SyntaxError) {
alert("JSON Syntax Error: " + err.message);
} else {
throw err; // unknown error, rethrow it
}
}
Is there a way to handle unknown or potential errors in JavaScript?
View Answer:
Interview Response: When prospective errors are relevant, we should deal with them immediately. It is not a good idea to address every conceivable or unexpected error. When encapsulating exceptions, it would be preferable to rethrow the catch to at least record the problem.
Code Example:
try {
...
readUser() // the potential error source
...
} catch (err) {
if (err instanceof ValidationError) {
// handle validation errors
} else if (err instanceof SyntaxError) {
// handle syntax errors
} else {
throw err; // unknown error, rethrow it
}
}