Error Handling in JavaScript
Error Handling: Error handling, "try..catch"
Can you briefly explain the behavior of the “try..catch” error handling process?
View Answer:
Interview Response: The try…catch construct has two main blocks, try and then catch blocks. First, the code in the try executes on the try block. If there is no error, it proceeds to execute and exit the code, skipping the catch. If there is an error in the try block, the catch gets invoked, and the error gets returned.
Technical Response: The try...catch construct has two main blocks: try, and then catch
Steps:
Steps:
- First, the code in try {...} executes.
- If there were no errors, then catch(err) is ignored: the execution reaches the end of try and goes on, skipping catch.
- If an error occurs, the try execution stops, and control flows to the beginning of catch(err). The err variable (we can use any name for it) contains an error object with details about what happened.
Code Example:
try {
alert('Start of try runs'); // (1) <--
lalala; // error, variable is not defined!
alert('End of try (never reached)'); // (2)
} catch (err) {
alert(`Error has occurred!`); // (3) <--
}
Can you explain how the JavaScript engine works with the “try..catch” block?
View Answer:
Interview Response: The most significant part of the interaction with the JavaScript engine is that the try..catch only works for runtime errors. The code must be runnable for `try..catch` to work. In other words, it should be valid JavaScript.
Technical Response: The most striking aspect of the interface with the JavaScript engine is that the try..catch statement only works for runtime failures. The code must be runnable for 'try..catch' to work. In other words, it should be legitimate JavaScript. It does not work if the code in the "try..catch" block incorrectly gets written. The JavaScript engine examines the code before running it. The errors that occur during the reading phase are called "parse-time" errors, and they are unrecoverable (from inside that code). This behavior is due to the engine's inability to comprehend the code. As a result, try...catch can only handle failures in "valid" code. Such mistakes commonly get referred to as "runtime errors" or "exceptions" in some instances.
Code Example:
try {
{{{{{{{{{{{{ // Syntax error will be invoked and not caught by catch handler
} catch(e) {
alert("The engine can't understand this code, it's invalid");
}
Does the “try..catch” block work synchronously or asynchronously?
View Answer:
Interview Response: The JavaScript try..catch works synchronously when executed. We cannot use asynchronous methods or functions inside the try block because the code gets set to execute later while the catch has already finished, and the code dies inside the try block.
Technical Response: The JavaScript try..catch method operates synchronously when running. If an exception occurs in "scheduled" code, such as setTimeout, try..catch does not catch it. After the engine has exited the try..catch construct, the function gets called. To catch an exception within a scheduled function, try..catch must be present.
Code Example:
try {
setTimeout(function () {
noSuchVariable; // script will die here
}, 1000);
} catch (e) {
alert("won't work");
}
//////// HOW TO FIX THIS ////////
// try..catch must be called inside of the setTimeout function
setTimeout(function () {
try {
noSuchVariable; // try..catch handles the error!
} catch {
alert('error is caught here!');
}
}, 1000);
How does the JavaScript error object work inside the try..catch?
View Answer:
Interview Response: The error object has two main properties for all built-in errors, including the name and message properties. The err.name reflects the name of the error like an undefined variable, which returns a ReferenceError. The err.message returns a text-based message reflecting the error details.
Technical Response: JavaScript generates an object containing its details when an error occurs. The object then gets passed as an argument to catch. The error object has two significant fields for all built-in errors: the name and message properties. Like an undefined variable, err.name reflects the name of the error and produces a ReferenceError. The err.message returns a textual message reflecting the error details. In addition to the name and message properties, other non-standard properties are available in most environments.
Code Example:
try {
lalala; // error, variable is not defined!
} catch (err) {
alert(err.name); // ReferenceError
alert(err.message); // lalala is not defined
alert(err.stack); // ReferenceError: lalala is not defined at (...call stack)
// Can also show an error as a whole
// The error is converted to string as "name: message"
alert(err); // ReferenceError: lalala is not defined
}
note
In addition to the name and message properties, other non-standard properties are available in most environments.
Can you explain what the stack error object property does?
View Answer:
Interview Response: The error object stack property returns a string with information about the sequence of nested calls that led to the error within the current call stack. It is commonly used for JavaScript debugging purposes and helps resolve issues within the code.
Code Example:
try {
lalala; // error, variable is not defined!
} catch (err) {
alert(err.stack); // ReferenceError: lalala is not defined at (...call stack)
}
What does the throw operator do in JavaScript?
View Answer:
Interview Response: The throw operator/statement throws a user-defined exception in simple terms. The current function terminates, and control hands off to the first catch block on the call stack.
Code Example:
function getRectArea(width, height) {
if (isNaN(width) || isNaN(height)) {
throw 'Parameter is not a number!';
}
}
try {
getRectArea(3, 'A');
} catch (e) {
console.error(e);
// expected output: "Parameter is not a number!"
}
///////////////////////////////////
// Standard errors
let error = new Error(message);
// or
let error = new SyntaxError(message);
let error = new ReferenceError(message);
// ...
///////////////////////////////////
// Standard error use
let error = new Error('Things happen o_O');
alert(error.name); // Error
alert(error.message); // Things happen o_O
note
The program terminates if no catch block exists among caller functions. JavaScript has many built-in constructors for standard errors: Error, SyntaxError, ReferenceError, TypeError, and others, and we can use them to create error objects.
What does it mean to rethrow an error in JavaScript?
View Answer:
Interview Response: When dealing with errors, handling them at the perimeter of your application is not always sufficient. By the time the error bubbles up, we have often lost a lot of the context in which the error gets thrown. People sometimes catch an error, record it locally somehow, and then rethrow it. Rethrowing is the basic concept of using a throw statement when there is no clear way to handle an error. This process maintains the original stack trace recorded by the error as you "pass it back up" the call stack.
Technical Response: There is no special "rethrow" keyword in JavaScript. You throw() the error you caught, which maintains the original stack trace recorded by the error as you "pass it back up" the call stack.
More specifically, the "rethrowing" approach gets described as follows:
More specifically, the "rethrowing" approach gets described as follows:
- All errors get caught.
- We examine the error object err in the catch(err)#123;...} block.
- We throw err if we don’t know how to handle it.
Code Example:
let json = '{ "age": 30 }'; // incomplete data
try {
let user = JSON.parse(json);
if (!user.name) {
throw new SyntaxError('Incomplete data: no name');
}
blabla(); // unexpected error
alert(user.name);
} catch (e) {
if (e instanceof SyntaxError) {
alert('JSON Error: ' + e.message);
} else {
throw e; // rethrow (*)
}
}
How does the try..catch..finally function in JavaScript error handling?
View Answer:
Interview Response: In JavaScript, the try..catch..finally statement works in an ordered fashion. The first try block is where code execution happens. The catch statement executes if an exception gets thrown in the try block. The finally statement block contains all of the code executed after the try and catch statements resolve. If the try block executes without errors, the finally block gets executed. If the try statement results in an error, it passes the error to the catch block, and then and only then does the finally statement run.
Code Example:
try {
//... try to execute the code ...
} catch (e) {
//... handle errors ...
} finally {
//... execute always ...
}
Are variables localized inside the “try..catch..finally” blocks?
View Answer:
Interview Response: Yes, as with everything in curly brackets ({...}), variables are localized to the “try..catch..finally” blocks individually. If a variable gets declared with one of the blocks, it is only accessible within that block.
Code Example:
let hello2 = 'Hello, JavaScript';
try {
let hello = 'hello';
console.log(hello); // returns "hello"
} catch (e) {
console.log(e.message);
} finally {
console.log(hello); // ReferenceError: hello is not defined
console.log(hello2); // returns "Hello, JavaScript" from the global variable
}
console.log(hello); // ReferenceError: hello is not defined
Errors can happen in any part of the JavaScript environment, including the global space. Is there a way to handle errors in the global window environment?
View Answer:
Interview Response: Yes, we can use the global handler (global catch) window.onerror that is part of the Web API.
Technical Response: Yes, we can use the global handler (global catch) window.onerror that is part of the Web API. The onerror property of the GlobalEventHandlers mixin is an EventHandler that processes error events. Error events fire at various targets for different kinds of errors, such as runtime errors or when a resource (such as an img or script tags) fails to load. Installing a global error event handler is useful for the automated collection of error reports.
Code Example:
Syntax: window.onerror = function(message, source, lineno, colno, error) { ... };
Syntax: window.onerror = function(message, source, lineno, colno, error) { ... };
window.onerror = function (message, url, line, col, error) {
alert(`${message}\n At ${line}:${col} of ${url}`);
};
function readData() {
badFunc(); // Whoops, something went wrong!
}
readData();