javascript
examples
examples.js⚡javascript
/**
* =====================================================
* 4.6 ERROR HANDLING WITH TRY-CATCH - EXAMPLES
* =====================================================
* Graceful error handling
*/
// =====================================================
// 1. BASIC TRY-CATCH
// =====================================================
console.log('--- Basic try-catch ---');
try {
const result = JSON.parse('{"name": "John"}');
console.log('Parsed:', result);
} catch (error) {
console.log('Error:', error.message);
}
// Without try-catch, this would crash
try {
const invalid = JSON.parse('not valid json');
} catch (error) {
console.log('Failed to parse:', error.message);
}
console.log('Program continues after error handling...');
// =====================================================
// 2. ERROR OBJECT PROPERTIES
// =====================================================
console.log('\n--- Error Object Properties ---');
try {
undefined.property;
} catch (error) {
console.log('Name:', error.name);
console.log('Message:', error.message);
console.log('Stack (first 100 chars):', error.stack?.substring(0, 100));
}
// =====================================================
// 3. THE FINALLY BLOCK
// =====================================================
console.log('\n--- Finally Block ---');
function exampleWithFinally(shouldFail) {
console.log(`\nRunning with shouldFail = ${shouldFail}`);
try {
console.log(' Try block executing...');
if (shouldFail) {
throw new Error('Intentional error');
}
console.log(' Try block completed successfully');
} catch (error) {
console.log(' Catch block:', error.message);
} finally {
console.log(' Finally block: Always runs!');
}
}
exampleWithFinally(false);
exampleWithFinally(true);
// =====================================================
// 4. FINALLY WITH RETURN
// =====================================================
console.log('\n--- Finally with Return ---');
function demonstrateFinally() {
try {
console.log('Try block');
return 'Return from try';
} finally {
console.log('Finally block executes before return');
}
}
console.log('Result:', demonstrateFinally());
// =====================================================
// 5. THROWING ERRORS
// =====================================================
console.log('\n--- Throwing Errors ---');
function divide(a, b) {
if (typeof a !== 'number' || typeof b !== 'number') {
throw new TypeError('Both arguments must be numbers');
}
if (b === 0) {
throw new Error('Division by zero');
}
return a / b;
}
try {
console.log('10 / 2 =', divide(10, 2));
console.log('10 / 0 =', divide(10, 0));
} catch (error) {
console.log('Error:', error.message);
}
try {
console.log("'10' / 2 =", divide('10', 2));
} catch (error) {
console.log('Error:', error.name, '-', error.message);
}
// =====================================================
// 6. ERROR TYPES
// =====================================================
console.log('\n--- Error Types ---');
// TypeError
try {
null.property;
} catch (error) {
console.log('TypeError caught:', error.message);
}
// RangeError
try {
const arr = new Array(-1);
} catch (error) {
console.log('RangeError caught:', error.message);
}
// SyntaxError (via JSON.parse)
try {
JSON.parse('{invalid}');
} catch (error) {
console.log('SyntaxError caught:', error.message);
}
// URIError
try {
decodeURIComponent('%');
} catch (error) {
console.log('URIError caught:', error.message);
}
// =====================================================
// 7. CHECKING ERROR TYPE
// =====================================================
console.log('\n--- Checking Error Type ---');
function handleError(error) {
if (error instanceof TypeError) {
console.log('Type Error:', error.message);
} else if (error instanceof RangeError) {
console.log('Range Error:', error.message);
} else if (error instanceof SyntaxError) {
console.log('Syntax Error:', error.message);
} else {
console.log('Other Error:', error.message);
}
}
try {
null.x;
} catch (e) {
handleError(e);
}
try {
new Array(-1);
} catch (e) {
handleError(e);
}
try {
JSON.parse('{');
} catch (e) {
handleError(e);
}
try {
throw new Error('custom');
} catch (e) {
handleError(e);
}
// =====================================================
// 8. CUSTOM ERROR CLASSES
// =====================================================
console.log('\n--- Custom Error Classes ---');
class ValidationError extends Error {
constructor(message, field) {
super(message);
this.name = 'ValidationError';
this.field = field;
}
}
class NetworkError extends Error {
constructor(message, statusCode) {
super(message);
this.name = 'NetworkError';
this.statusCode = statusCode;
}
}
function validateUser(user) {
if (!user.name) {
throw new ValidationError('Name is required', 'name');
}
if (!user.email) {
throw new ValidationError('Email is required', 'email');
}
if (!user.email.includes('@')) {
throw new ValidationError('Invalid email format', 'email');
}
return true;
}
try {
validateUser({ name: 'John' });
} catch (error) {
if (error instanceof ValidationError) {
console.log(`Validation Error on field '${error.field}': ${error.message}`);
}
}
// =====================================================
// 9. RE-THROWING ERRORS
// =====================================================
console.log('\n--- Re-throwing Errors ---');
function processJSON(jsonString) {
try {
return JSON.parse(jsonString);
} catch (error) {
console.log('Logging error:', error.message);
// Re-throw with more context
throw new Error(`Failed to parse JSON: ${error.message}`);
}
}
try {
const data = processJSON('invalid');
} catch (error) {
console.log('Final handler:', error.message);
}
// =====================================================
// 10. NESTED TRY-CATCH
// =====================================================
console.log('\n--- Nested try-catch ---');
function outerFunction() {
try {
console.log('Outer try');
innerFunction();
} catch (error) {
console.log('Outer catch:', error.message);
}
}
function innerFunction() {
try {
console.log('Inner try');
throw new Error('Inner error');
} catch (error) {
console.log('Inner catch:', error.message);
// Re-throw
throw new Error('Wrapped: ' + error.message);
}
}
outerFunction();
// =====================================================
// 11. DEFAULT VALUE PATTERN
// =====================================================
console.log('\n--- Default Value Pattern ---');
function safeParse(jsonString, defaultValue = null) {
try {
return JSON.parse(jsonString);
} catch {
return defaultValue;
}
}
console.log(safeParse('{"valid": true}')); // { valid: true }
console.log(safeParse('invalid')); // null
console.log(safeParse('invalid', {})); // {}
console.log(safeParse('invalid', [])); // []
// =====================================================
// 12. ERROR WRAPPER FUNCTION
// =====================================================
console.log('\n--- Error Wrapper ---');
function tryCatch(fn, errorHandler) {
return function (...args) {
try {
return fn(...args);
} catch (error) {
return errorHandler(error);
}
};
}
const riskyFunction = (x) => {
if (x < 0) throw new Error('Negative number');
return x * 2;
};
const safeFunction = tryCatch(riskyFunction, (error) => {
console.log('Handled:', error.message);
return 0;
});
console.log('Safe(5):', safeFunction(5)); // 10
console.log('Safe(-1):', safeFunction(-1)); // 0 (handled)
// =====================================================
// 13. ERROR AGGREGATION
// =====================================================
console.log('\n--- Error Aggregation ---');
function validateForm(data) {
const errors = [];
if (!data.username || data.username.length < 3) {
errors.push(new Error('Username must be at least 3 characters'));
}
if (!data.email || !data.email.includes('@')) {
errors.push(new Error('Valid email is required'));
}
if (!data.password || data.password.length < 8) {
errors.push(new Error('Password must be at least 8 characters'));
}
if (errors.length > 0) {
// Create AggregateError with all validation errors
const aggregateError = new AggregateError(
errors,
`Form validation failed with ${errors.length} error(s)`
);
throw aggregateError;
}
return true;
}
try {
validateForm({ username: 'ab', email: 'invalid', password: '123' });
} catch (error) {
if (error instanceof AggregateError) {
console.log('AggregateError:', error.message);
console.log('Individual errors:');
for (const e of error.errors) {
console.log(' -', e.message);
}
}
}
// =====================================================
// 14. RESOURCE CLEANUP
// =====================================================
console.log('\n--- Resource Cleanup Pattern ---');
class Database {
constructor() {
this.connected = false;
}
connect() {
console.log('Database connected');
this.connected = true;
}
query(sql) {
if (!this.connected) {
throw new Error('Not connected');
}
if (sql.includes('error')) {
throw new Error('Query failed');
}
return { data: 'result' };
}
disconnect() {
console.log('Database disconnected');
this.connected = false;
}
}
function performDatabaseOperation(sql) {
const db = new Database();
try {
db.connect();
const result = db.query(sql);
console.log('Query result:', result);
return result;
} catch (error) {
console.log('Database error:', error.message);
return null;
} finally {
db.disconnect(); // Always disconnect
}
}
console.log('\nSuccessful query:');
performDatabaseOperation('SELECT * FROM users');
console.log('\nFailed query:');
performDatabaseOperation('SELECT error FROM table');
// =====================================================
// 15. PRACTICAL EXAMPLE: API RESPONSE HANDLER
// =====================================================
console.log('\n--- API Response Handler ---');
class APIError extends Error {
constructor(message, status, data) {
super(message);
this.name = 'APIError';
this.status = status;
this.data = data;
}
}
function handleAPIResponse(response) {
try {
// Simulate response parsing
const data = JSON.parse(response);
if (data.error) {
throw new APIError(data.error, data.status, data);
}
return data;
} catch (error) {
if (error instanceof APIError) {
console.log(`API Error (${error.status}): ${error.message}`);
} else if (error instanceof SyntaxError) {
console.log('Invalid JSON response');
} else {
console.log('Unexpected error:', error.message);
}
return null;
}
}
// Test different scenarios
console.log('\nValid response:');
console.log(handleAPIResponse('{"success": true, "data": [1, 2, 3]}'));
console.log('\nAPI error:');
console.log(handleAPIResponse('{"error": "Not found", "status": 404}'));
console.log('\nInvalid JSON:');
console.log(handleAPIResponse('not json'));
// =====================================================
// SUMMARY
// =====================================================
console.log('\n--- Summary ---');
console.log(`
Error Handling Basics:
• try { code } catch (e) { handle } finally { cleanup }
• throw new Error("message") to throw errors
• error.name, error.message, error.stack
Error Types:
• Error - base class
• TypeError - wrong type
• RangeError - value out of range
• SyntaxError - invalid syntax (JSON.parse)
• ReferenceError - undefined variable
• URIError - invalid URI encoding
Custom Errors:
• class CustomError extends Error
• Add custom properties (code, field, status)
• Use instanceof to check type
Best Practices:
• Don't swallow errors silently
• Use finally for cleanup
• Include helpful error messages
• Validate inputs early
• Re-throw when appropriate
`);