Asynchronous JavaScript

Node.js is designed for asynchronous operations. Understanding how to handle tasks like database queries or file reading without blocking the main thread is vital.

1. Callbacks (Legacy)

The original way to handle async code. However, it often leads to "Callback Hell."

fs.readFile('file.txt', 'utf8', (err, data) => {
  if (err) return console.log(err);
  console.log(data);
});

2. Promises

Represent the eventual completion (or failure) of an asynchronous operation.

const myPromise = new Promise((resolve, reject) => {
  const success = true;
  if (success) resolve('Done!');
  else reject('Error!');
});

myPromise
  .then(res => console.log(res))
  .catch(err => console.error(err));

3. Async / Await (Modern)

Syntactic sugar on top of Promises. It makes asynchronous code look and behave a bit more like synchronous code.

async function fetchData() {
  try {
    const response = await fetch('https://api.example.com/data');
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error('Fetch failed:', error);
  }
}

fetchData();
Best Practice: Always use try/catch blocks with async/awaitto ensure your application doesn't crash when an operation fails.