Handling Errors in JavaScript (try...catch)

Error Handling with try...catch

Error handling allows you to handle errors without crashing the application.
Basic syntax: try { code_that_might_fail } catch (error) { error_handling }

Basic Example

try {
    let nonexistentObject = null;
    console.log(nonexistentObject.property);
} catch (error) {
    console.log("An error occurred:", error.message);
}

console.log("The program continues after the error");

Common Error Types

TypeError

// TypeError: when a value of the wrong type is used
console.log("--- TypeError ---");
try {
    let number = null;
    number.toUpperCase(); // TypeError: cannot read property of null
} catch (error) {
    console.log(`Error type: ${error.name}`);
    console.log(`Message: ${error.message}`);
}

ReferenceError

// ReferenceError: when an undeclared variable is used
console.log("--- ReferenceError ---");
try {
    console.log(nonexistentVariable); // ReferenceError
} catch (error) {
    console.log(`Error type: ${error.name}`);
    console.log(`Message: ${error.message}`);
}

SyntaxError

// SyntaxError: a syntax error (usually detected before execution)
console.log("--- SyntaxError (simulation) ---");
try {
    // A SyntaxError cannot be caught with try...catch because it prevents execution
    // Example: eval() with invalid code
    eval("let x = ;"); // Invalid JavaScript code
} catch (error) {
    console.log(`Error type: ${error.name}`);
    console.log(`Message: ${error.message}`);
}

RangeError

// RangeError: when a value is outside the acceptable range
console.log("--- RangeError ---");
try {
    let array = new Array(-1); // A negative size is impossible
} catch (error) {
    console.log(`Error type: ${error.name}`);
    console.log(`Message: ${error.message}`);
}

TRY...CATCH...FINALLY

// The finally block ALWAYS runs, whether there is an error or not
console.log("--- Example with finally ---");

function finallyExample(errorCase) {
    try {
        console.log("Processing started");

        if (errorCase) {
            throw new Error("Simulated error");
        }

        console.log("Processing succeeded");
        return "Success";
    } catch (error) {
        console.log("Error caught:", error.message);
        return "Failure";
    } finally {
        console.log("Cleanup (finally always runs)");
    }
}

console.log("Result without error:", finallyExample(false));
console.log("Result with error:", finallyExample(true));

Throwing Custom Errors (THROW)

// We can throw our own errors with throw
function divide(a, b) {
    try {
        if (typeof a !== 'number' || typeof b !== 'number') {
            throw new TypeError("The parameters must be numbers");
        }

        if (b === 0) {
            throw new Error("Division by zero is impossible");
        }

        return a / b;
    } catch (error) {
        console.log(`Error in divide(): ${error.message}`);
        throw error; // Rethrow the error for the calling code
    } finally {
        console.log("Cleanup (finally always runs)");
    }
}