Skip to content

Latest commit

 

History

History
179 lines (138 loc) · 4.75 KB

module-4.7-error-handling-in-nodejs.md

File metadata and controls

179 lines (138 loc) · 4.75 KB

1. Synchronous Error Handling:

Node.js uses try-catch blocks for synchronous error handling. Here's an example:

try {
  const result = someSynchronousFunction();
  console.log(result);
} catch (error) {
  console.error('An error occurred:', error.message);
}

2. Asynchronous Error Handling (Callbacks):

When working with asynchronous code that uses callbacks, it's a common practice to pass errors as the first argument to the callback function:

function readAndProcessFile(filename, callback) {
  fs.readFile(filename, 'utf8', (err, data) => {
    if (err) {
      callback(err); // Pass the error to the callback
    } else {
      // Process the file data
      callback(null, data);
    }
  });
}

readAndProcessFile('example.txt', (err, data) => {
  if (err) {
    console.error('Error reading file:', err.message);
  } else {
    console.log('File data:', data);
  }
});

3. Promises and Async/Await:

With Promises and Async/Await, error handling becomes more structured. Here's an example:

function readFileAsync(filename) {
  return new Promise((resolve, reject) => {
    fs.readFile(filename, 'utf8', (err, data) => {
      if (err) {
        reject(err); // Reject with the error
      } else {
        resolve(data); // Resolve with the data
      }
    });
  });
}

async function main() {
  try {
    const data = await readFileAsync('example.txt');
    console.log('File data:', data);
  } catch (error) {
    console.error('Error reading file:', error.message);
  }
}

main();

4. Event Emitters and Error Events:

Node.js's event-driven architecture allows you to handle errors using the 'error' event:

const EventEmitter = require('events');

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();

myEmitter.on('error', (error) => {
  console.error('Error occurred:', error.message);
});

myEmitter.emit('error', new Error('Custom error'));

5. Handling Unhandled Rejections:

In Node.js, unhandled promise rejections can terminate the application. To handle them, you can add an event listener:

process.on('unhandledRejection', (reason, promise) => {
  console.error('Unhandled Rejection:', reason);
  // You can log, report, or handle the rejection as needed
});

6. Express.js Error Handling:

In Express.js, you can handle errors using middlewares. For example:

app.get('/error', (req, res, next) => {
  next(new Error('An example error occurred'));
});

app.use((err, req, res, next) => {
  console.error('Error:', err.message);
  res.status(500).send('Internal Server Error');
});

These examples cover various aspects of error handling in Node.js, including synchronous and asynchronous code, event emitters, and unhandled rejections. Effective error handling is essential for building reliable and maintainable Node.js applications.

7. Handling Errors in Streams:

Node.js provides a robust way to handle errors in streams using the error event. For example:

const fs = require('fs');
const readStream = fs.createReadStream('example.txt');

readStream.on('data', (data) => {
  console.log('Data:', data);
});

readStream.on('error', (error) => {
  console.error('Error reading stream:', error.message);
});

readStream.on('end', () => {
  console.log('Stream reading completed.');
});

8. Custom Error Handling:

You can create custom error classes for specific types of errors to enhance error handling and provide better context for debugging:

class CustomError extends Error {
  constructor(message, errorCode) {
    super(message);
    this.name = 'CustomError';
    this.errorCode = errorCode;
  }
}

try {
  throw new CustomError('Custom error message', 500);
} catch (error) {
  if (error instanceof CustomError) {
    console.error(`Custom Error (Code ${error.errorCode}): ${error.message}`);
  } else {
    console.error('Unknown Error:', error.message);
  }
}

9. Handling Errors in Promises with Express.js:

When working with Express.js and Promises, you can handle errors using Promise rejections and Express error handling middleware:

app.get('/async-error', async (req, res, next) => {
  try {
    await someAsyncFunction();
    res.send('Success');
  } catch (error) {
    next(error); // Pass the error to Express error handling middleware
  }
});

app.use((err, req, res, next) => {
  console.error('Error:', err.message);
  res.status(500).send('Internal Server Error');
});

These examples illustrate various ways to handle errors in Node.js, from basic try-catch blocks to more advanced techniques like error events, custom error classes, and error handling in specific contexts like Express.js or streams. Proper error handling is essential for building robust Node.js applications.