Async Programming in Node.js

Master asynchronous programming with callbacks, promises, and async/await. Learn to write non-blocking code that scales.

Asynchronous programming is at the heart of Node.js. Unlike traditional synchronous code, async operations don't block the execution of other code while waiting for I/O operations.

Why Async Matters

Node.js uses a single-threaded event loop. Async programming allows Node.js to handle thousands of concurrent operations without creating new threads for each request.

Callbacks

The original async pattern in Node.js. Callbacks are functions passed as arguments to be executed after an async operation completes.

Promises

Promises provide a cleaner way to handle async operations. They represent a value that may be available now, later, or never.

Async/Await

The modern approach to async programming. Async/await makes asynchronous code look and behave like synchronous code, making it easier to read and maintain.

Error Handling

Proper error handling is crucial in async code. Unhandled promise rejections can crash your application.

Code Examples

Callback Pattern

callbacks.js
const fs = require('fs');

// Reading a file with callbacks
fs.readFile('data.txt', 'utf8', (err, data) => {
  if (err) {
    console.error('Error reading file:', err);
    return;
  }
  console.log('File contents:', data);
});

console.log('This runs before file is read!');

Promises

promises.js
const fs = require('fs').promises;

// Reading a file with promises
fs.readFile('data.txt', 'utf8')
  .then(data => {
    console.log('File contents:', data);
    return fs.writeFile('copy.txt', data);
  })
  .then(() => {
    console.log('File copied successfully');
  })
  .catch(err => {
    console.error('Error:', err);
  });

Async/Await

async-await.js
const fs = require('fs').promises;

async function copyFile() {
  try {
    const data = await fs.readFile('data.txt', 'utf8');
    console.log('File contents:', data);

    await fs.writeFile('copy.txt', data);
    console.log('File copied successfully');

    return data;
  } catch (err) {
    console.error('Error:', err);
    throw err;
  }
}

// Call the async function
copyFile()
  .then(data => console.log('Done!'))
  .catch(err => console.error('Failed'));

Frequently Asked Questions

Should I use callbacks, promises, or async/await?

Prefer async/await for new code as it's the most readable. Use promises when you need features like Promise.all() for concurrent operations. Callbacks are mainly used with older APIs.

How do I run multiple async operations in parallel?

Use Promise.all() to run multiple promises concurrently. For example: const [user, posts] = await Promise.all([fetchUser(), fetchPosts()]). This is much faster than awaiting each sequentially.

What happens if I forget to handle a promise rejection?

Unhandled promise rejections will eventually crash your Node.js application (Node 15+). Always use try/catch with async/await or .catch() with promises.

Need Node.js Help?

Slashdev.io builds production-ready Node.js applications for businesses of all sizes.

Get in Touch