Learn how setTimeout works in the Event Loop. This demo helps understand the macrotask queue and async execution order.
1console.log('Start');
2
3setTimeout(() => {
4 console.log('Timeout callback executed');
5}, 0);
6
7console.log('End');
Explore how Promise.resolve() creates microtasks. Understand the difference between microtask and macrotask priority.
1console.log('Start');
2
3let promise = Promise.resolve('Hello Promise');
4promise.then((value) => {
5 console.log('Promise resolved:', value);
6});
7
8console.log('End');
Direct comparison between setTimeout (macrotask) and Promise (microtask). Microtasks are always prioritized over macrotasks.
1console.log('Start');
2
3setTimeout(() => {
4 console.log('Timeout (Macrotask)');
5}, 0);
6
7Promise.resolve().then(() => {
8 console.log('Promise (Microtask)');
9});
10
11console.log('End');
Complex demo with multiple setTimeout and Promise chains. Observe execution order according to Event Loop rules.
1console.log('A');
2
3setTimeout(() => {
4 console.log('B');
5}, 0);
6
7Promise.resolve().then(() => {
8 console.log('C');
9 return Promise.resolve();
10}).then(() => {
11 console.log('D');
12});
13
14setTimeout(() => {
15 console.log('E');
16}, 0);
17
18console.log('F');
Learn how Promise chains work. Each .then() creates a new microtask after the previous callback completes.
1console.log('Start');
2
3Promise.resolve(1)
4 .then((value) => {
5 console.log('First then:', value);
6 return value * 2;
7 })
8 .then((value) => {
9 console.log('Second then:', value);
10 return value + 1;
11 })
12 .then((value) => {
13 console.log('Third then:', value);
14 });
15
16console.log('End');
Multiple timers with different delays. Understand how WebAPI handles timers and queues callbacks to macrotask queue.
1console.log('Start');
2
3setTimeout(() => {
4 console.log('Timer 1 (100ms)');
5}, 100);
6
7setTimeout(() => {
8 console.log('Timer 2 (0ms)');
9}, 0);
10
11setTimeout(() => {
12 console.log('Timer 3 (50ms)');
13}, 50);
14
15setTimeout(() => {
16 console.log('Timer 4 (0ms)');
17}, 0);
18
19Promise.resolve().then(() => {
20 console.log('Promise (Microtask)');
21});
22
23console.log('End');
Demo the power of microtask queue. Nested Promise.resolve() creates consecutive microtask chains.
1console.log('1');
2
3Promise.resolve().then(() => {
4 console.log('2');
5 Promise.resolve().then(() => console.log('3'));
6});
7
8Promise.resolve().then(() => {
9 console.log('4');
10});
11
12console.log('5');
Nested Promises create complex patterns. Learn how microtasks are queued in depth-first order.
1console.log('Start');
2
3Promise.resolve()
4 .then(() => {
5 console.log('Promise 1');
6 return Promise.resolve()
7 .then(() => console.log('Nested Promise 1'))
8 .then(() => console.log('Nested Promise 2'));
9 })
10 .then(() => console.log('Promise 2'));
11
12console.log('End');
Compare queueMicrotask() with Promise.resolve().then(). Both create microtasks with similar priority.
1console.log('1');
2
3queueMicrotask(() => console.log('2'));
4
5Promise.resolve().then(() => console.log('3'));
6
7queueMicrotask(() => console.log('4'));
8
9console.log('5');
Explore Promise.resolve() creating immediately resolved Promises. Callbacks are still queued to microtasks.
1console.log('A');
2
3Promise.resolve('Immediate Value')
4 .then(value => {
5 console.log('B:', value);
6 return 'New Value';
7 })
8 .then(value => {
9 console.log('C:', value);
10 });
11
12console.log('D');
Multiple independent Promises running in parallel. All callbacks are queued to microtasks simultaneously.
1console.log('Start');
2
3Promise.resolve(1).then(x => console.log('Promise 1:', x));
4Promise.resolve(2).then(x => console.log('Promise 2:', x));
5Promise.resolve(3).then(x => console.log('Promise 3:', x));
6
7setTimeout(() => console.log('Timer 1'), 0);
8setTimeout(() => console.log('Timer 2'), 0);
9
10console.log('End');
Timers containing Promises and vice versa. Observe how microtasks are processed within macrotask callbacks.
1console.log('Start');
2
3setTimeout(() => {
4 console.log('Timer start');
5 Promise.resolve().then(() => console.log('Promise in timer'));
6 console.log('Timer end');
7}, 0);
8
9Promise.resolve().then(() => {
10 console.log('Promise start');
11 setTimeout(() => console.log('Timer in promise'), 0);
12 console.log('Promise end');
13});
14
15console.log('End');
Compare Promise.all() with individual Promises. Understand how Promise.all() works with resolved promises.
1console.log('Start');
2
3const promise1 = Promise.resolve(1);
4const promise2 = Promise.resolve(2);
5const promise3 = Promise.resolve(3);
6
7Promise.all([promise1, promise2, promise3])
8 .then(values => {
9 console.log('Promise.all resolved:', values);
10 });
11
12// Compare with individual promises
13promise1.then(val => console.log('Individual 1:', val));
14promise2.then(val => console.log('Individual 2:', val));
15promise3.then(val => console.log('Individual 3:', val));
16
17console.log('End');
Simulate fetch requests with Promise chains. Learn how network requests create Promise and callback sequences.
1console.log('Start');
2
3// Simulated fetch request
4fetch('https://api.example.com/data')
5 .then(response => {
6 console.log('Fetch resolved:', response);
7 return response;
8 })
9 .then(data => {
10 console.log('Data processed:', data);
11 });
12
13// Other async operations
14setTimeout(() => {
15 console.log('Timer during fetch');
16}, 0);
17
18Promise.resolve().then(() => {
19 console.log('Promise during fetch');
20});
21
22console.log('End');
How Promises handle errors with .catch(). Errors don't affect other async operations in the queue.
1console.log('Start');
2
3Promise.resolve()
4 .then(() => {
5 console.log('First promise');
6 throw new Error('Something went wrong');
7 })
8 .then(() => {
9 console.log('This will not run');
10 })
11 .catch(error => {
12 console.log('Caught error:', error.message);
13 return 'Error handled';
14 })
15 .then(result => {
16 console.log('After catch:', result);
17 });
18
19setTimeout(() => {
20 console.log('Timer still runs');
21}, 0);
22
23console.log('End');
Recursion with setTimeout avoids stack overflow. Each recursive call creates a new macrotask.
1console.log('Start recursion');
2
3function countdown(n) {
4 console.log('Countdown:', n);
5
6 if (n <= 0) {
7 console.log('Done!');
8 return;
9 }
10
11 // Async recursion with setTimeout
12 setTimeout(() => {
13 countdown(n - 1);
14 }, 0);
15}
16
17countdown(3);
18console.log('Recursion initiated');
Sync recursion keeps all calls on the call stack. Observe call stack growth and return sequence.
1console.log('Start sync recursion');
2
3function factorial(n) {
4 console.log('Calculating factorial of:', n);
5
6 if (n <= 1) {
7 console.log('Base case reached');
8 return 1;
9 }
10
11 // Sync recursion - each call stays on call stack
12 const result = n * factorial(n - 1);
13 console.log('Returning for n =', n, ', result =', result);
14 return result;
15}
16
17const result = factorial(4);
18console.log('Final result:', result);
19console.log('Sync recursion complete');
Traditional callback pattern before Promises. Understand 'callback hell' and why Promises were created.
1console.log('Start');
2
3function asyncOperation(callback) {
4 setTimeout(() => {
5 console.log('Async operation complete');
6 callback('Result data');
7 }, 0);
8}
9
10function asyncOperation2(data, callback) {
11 setTimeout(() => {
12 console.log('Second operation with:', data);
13 callback('Final result');
14 }, 0);
15}
16
17// Callback pattern (before Promises)
18asyncOperation((result1) => {
19 console.log('First callback:', result1);
20
21 asyncOperation2(result1, (result2) => {
22 console.log('Second callback:', result2);
23 });
24});
25
26console.log('End');
Most complex demo mixing setTimeout, Promise, nested async. Test your understanding of Event Loop mechanics.
1console.log('A');
2
3setTimeout(() => {
4 console.log('B');
5 Promise.resolve().then(() => console.log('C'));
6}, 0);
7
8Promise.resolve()
9 .then(() => {
10 console.log('D');
11 setTimeout(() => console.log('E'), 0);
12 return Promise.resolve();
13 })
14 .then(() => console.log('F'));
15
16setTimeout(() => console.log('G'), 0);
17
18Promise.resolve().then(() => {
19 console.log('H');
20 Promise.resolve().then(() => console.log('I'));
21});
22
23console.log('J');
Modern async/await syntax built on Promises. Learn how async functions suspend and resume execution through the Event Loop.
1console.log('Start');
2
3async function getData() {
4 console.log('1. Async function started');
5
6 // await makes function pause here
7 const result = await Promise.resolve('Hello from Promise');
8
9 console.log('2. After await:', result);
10 return 'Function complete';
11}
12
13// Call async function
14getData().then(data => {
15 console.log('3. Async function result:', data);
16});
17
18console.log('End - this runs before await resumes');
Advanced async/await example with multiple awaits, try-catch-finally blocks, and error handling. Master complex async patterns and exception handling.
1console.log('🚀 Start complex async/await');
2
3async function fetchUserData() {
4 console.log('1. 📡 Starting user data fetch...');
5
6 try {
7 console.log('2. 🔍 Entering try block');
8
9 // First await - simulate user API call
10 const userResponse = await Promise.resolve({
11 id: 123,
12 name: 'John Doe',
13 email: 'john@example.com'
14 });
15
16 console.log('3. ✅ User data received:', userResponse.name);
17
18 // Second await - simulate posts API call
19 const postsResponse = await Promise.resolve([
20 { id: 1, title: 'First Post', userId: userResponse.id },
21 { id: 2, title: 'Second Post', userId: userResponse.id }
22 ]);
23
24 console.log('4. ✅ Posts data received:', postsResponse.length, 'posts');
25
26 return {
27 user: userResponse,
28 posts: postsResponse,
29 status: 'success'
30 };
31
32 } catch (error) {
33 console.log('5. ❌ Error caught:', error.message);
34 return {
35 user: null,
36 posts: [],
37 status: 'error',
38 error: error.message
39 };
40
41 } finally {
42 console.log('6. 🧹 Finally block - cleaning up resources');
43 console.log('7. 📊 Logging analytics data...');
44 }
45}
46
47// Start the async operation
48console.log('8. 🎯 Calling fetchUserData...');
49
50fetchUserData().then(result => {
51 console.log('9. 🎉 Final result:', result.status);
52 console.log('10. 👤 User:', result.user.name);
53});
54
55console.log('11. ⚡ Synchronous code continues...');
56
57setTimeout(() => {
58 console.log('12. ⏰ Timer callback - this runs after all async operations');
59}, 0);
60
61console.log('13. 🏁 End of synchronous execution');