DEV Community

Cover image for JavaScript Event Loop & Promises Explained: Async Programming Made Easy
Cameron Lucas
Cameron Lucas

Posted on

JavaScript Event Loop & Promises Explained: Async Programming Made Easy

JavaScript's Async Superpower: The Event Loop & Promises

Ever ordered food at a restaurant and wondered how the kitchen juggles multiple orders at once? The chef (JavaScript) prepares one dish at a time, but they don't just sit idle while waiting for the oven to finish baking your pizza. Instead, they move on to prepare the next dish. This is exactly how JavaScript's event loop worksβ€”handling tasks efficiently while waiting on others. πŸš€

JavaScript is an idiot sandwhich

But what happens when you need something done ASAP, like getting a drink while waiting for food? That's where Promises come in, ensuring tasks complete when ready without blocking everything else.

If you've ever run into mysterious async behavior, buckle up! We're diving into the event loop and Promises to demystify how JavaScript actually handles asynchronous tasks.


What is the JavaScript Event Loop?

JavaScript is single-threaded, meaning it can only do one thing at a time. However, thanks to the event loop, it can appear to multitask by juggling asynchronous operations like fetching data, handling user input, and running timers.

Ricky Bobby First or Last

🚦 How the Event Loop Works

  1. Call Stack (Synchronous Tasks) – JavaScript executes code line by line in a stack.
  2. Web APIs (Async Tasks) – Certain operations like setTimeout, fetch(), and event listeners are handled outside the stack.
  3. Callback Queue (Macrotasks) – Once an async task completes, its callback moves here.
  4. Microtask Queue (Higher Priority) – Includes Promise callbacks, executed before the macrotask queue.
  5. Event Loop Checks & Executes – The event loop constantly checks if the call stack is empty and processes queued tasks.

πŸ›  Code Example: The Event Loop in Action

console.log('Start');

setTimeout(() => {
    console.log('Timeout Callback');
}, 0);

Promise.resolve().then(() => {
    console.log('Promise Callback');
});

console.log('End');
Enter fullscreen mode Exit fullscreen mode

πŸ” Expected Output:

Start
End
Promise Callback
Timeout Callback
Enter fullscreen mode Exit fullscreen mode

πŸ”‘ Why?

  1. console.log('Start') runs immediately.
  2. setTimeout sends its callback to the Web API, scheduling it for later.
  3. Promise.resolve().then(...) goes into the Microtask Queue.
  4. console.log('End') runs before any async tasks.
  5. The Microtask Queue (Promises) executes before the Macrotask Queue (setTimeout), so the Promise logs first.

JavaScript Promises: How They Work & Why They Matter

Before Promises, we had callbacks, which led to deeply nested, unreadable code known as "callback hell". Promises make async operations cleaner and more manageable.

Callback Hell

πŸ— Creating a Promise

const fetchData = () => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('Data received!');
        }, 2000);
    });
};

fetchData().then(response => console.log(response));
Enter fullscreen mode Exit fullscreen mode

What happens?

  • fetchData() returns a Promise that resolves after 2 seconds.
  • .then() waits for it to complete before logging the response.

πŸ” Chaining Promises

Multiple async operations? No problem!

fetchData()
    .then(data => {
        console.log(data);
        return 'Next step';
    })
    .then(step => console.log(step));
Enter fullscreen mode Exit fullscreen mode

Each .then() returns a new Promise, allowing sequential execution.


Understanding JavaScript Promise Methods

When dealing with multiple asynchronous operations, JavaScript provides built-in Promise methods to simplify handling multiple Promises. These methods help determine how and when Promises resolve or reject, making async code more predictable and efficient.

Cool Spongebob

πŸ“Œ Why Use Promise Methods?

  • Better control over multiple async operations – Execute them concurrently or sequentially.
  • Optimize performance – Avoid unnecessary delays or failures.
  • Improve error handling – Gracefully manage failures across multiple Promises.

πŸ”— Promise.all() – Running Multiple Promises in Parallel

This method takes an array of Promises and resolves when all of them complete.

const p1 = Promise.resolve('One');
const p2 = new Promise(res => setTimeout(() => res('Two'), 2000));
const p3 = new Promise(res => setTimeout(() => res('Three'), 1000));

Promise.all([p1, p2, p3]).then(values => console.log(values));
// ['One', 'Two', 'Three'] (After 2 seconds)
Enter fullscreen mode Exit fullscreen mode

🏎 Promise.race() – First One Wins

Returns the first resolved or rejected Promise.

Promise.race([p1, p2, p3]).then(value => console.log(value));
// 'One' (since p1 resolves immediately)
Enter fullscreen mode Exit fullscreen mode

πŸ”„ Promise.allSettled() – Wait for Everything, Regardless of Success

Resolves when all Promises settle (resolve or reject), returning the results.

Promise.allSettled([p1, p2, Promise.reject('Error')])
  .then(results => console.log(results));
Enter fullscreen mode Exit fullscreen mode

🚨 Promise.any() – First Successful Promise

Similar to race(), but ignores rejections and resolves to the first fulfilled Promise.

Promise.any([
  Promise.reject('Fail 1'),
  Promise.reject('Fail 2'),
  Promise.resolve('Success')
]).then(value => console.log(value));
// 'Success'
Enter fullscreen mode Exit fullscreen mode

Summary: Key Takeaways

βœ… The Event Loop ensures JavaScript handles async tasks efficiently.
βœ… Microtask Queue (Promises) always executes before the Macrotask Queue (setTimeout, etc.).
βœ… Promises provide a cleaner way to handle async operations, replacing callback hell.
βœ… Promise methods like all, race, allSettled, and any help manage multiple async tasks.
βœ… Understanding the event loop helps debug async behavior and optimize performance.

πŸš€ Up Next: Async/Await – The Next Level of Promises!

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

Top comments (0)

SurveyJS custom survey software

JavaScript Form Builder UI Component

Generate dynamic JSON-driven forms directly in your JavaScript app (Angular, React, Vue.js, jQuery) with a fully customizable drag-and-drop form builder. Easily integrate with any backend system and retain full ownership over your data, with no user or form submission limits.

Learn more

πŸ‘‹ Kindness is contagious

Please leave a ❀️ or a friendly comment on this post if you found it helpful!

Okay