Home
Jobs

Event Loop & Asynchronous Programming Interview Questions

Comprehensive event loop & asynchronous programming interview questions and answers for Node.js. Prepare for your next job interview with expert guidance.

29 Questions Available

Questions Overview

1. What is the Event Loop in Node.js and how does it work?

Advanced

2. Explain the difference between Promises, async/await, and callbacks in Node.js.

Moderate

3. What is the microtask queue and how does it relate to the event loop?

Advanced

4. How do you handle errors in asynchronous operations?

Moderate

5. What is the purpose of the EventEmitter class in Node.js?

Moderate

6. How does Node.js handle CPU-intensive tasks without blocking the event loop?

Advanced

7. What are the best practices for handling Promise chains?

Moderate

8. How do you implement custom async iterators in Node.js?

Advanced

9. What is the difference between parallel and concurrent execution in Node.js?

Advanced

10. How do you implement async error handling patterns?

Moderate

11. How does Node.js handle timer functions internally?

Advanced

12. What are async hooks in Node.js and how are they used?

Advanced

13. How do you implement custom promises in Node.js?

Advanced

14. What are the different phases of Promise execution?

Moderate

15. How do you implement throttling and debouncing in Node.js?

Moderate

16. How do you handle race conditions in async operations?

Advanced

17. Explain the concept of event loop starvation and how to prevent it.

Advanced

18. How do you implement cancellable promises in Node.js?

Advanced

19. What are the patterns for handling concurrent database operations?

Advanced

20. How do you implement retry mechanisms for async operations?

Moderate

21. What are the strategies for handling memory leaks in async operations?

Advanced

22. How do you implement async iterators for custom data sources?

Advanced

23. What are the patterns for implementing rate limiting in async operations?

Advanced

24. How do you handle timeouts in async operations?

Moderate

25. How do you implement async dependency injection?

Advanced

26. What are the patterns for handling distributed events in Node.js?

Advanced

27. How do you implement async middleware patterns?

Advanced

28. What are the strategies for handling backpressure in async streams?

Advanced

29. How do you implement async error boundaries?

Advanced

1. What is the Event Loop in Node.js and how does it work?

Advanced

The Event Loop is the mechanism that allows Node.js to perform non-blocking I/O operations despite JavaScript being single-threaded. It works in phases: 1) Timers (setTimeout, setInterval), 2) Pending callbacks (I/O callbacks), 3) Idle, prepare (internal use), 4) Poll (new I/O events), 5) Check (setImmediate), 6) Close callbacks. Each phase has a FIFO queue of callbacks to execute. Example: console.log('1'); setTimeout(() => console.log('2'), 0); Promise.resolve().then(() => console.log('3')); console.log('4'); // Output: 1, 4, 3, 2

2. Explain the difference between Promises, async/await, and callbacks in Node.js.

Moderate

Different asynchronous patterns in Node.js serve different purposes: 1) Callbacks: Traditional pattern with error-first callback style. Example: fs.readFile('file.txt', (err, data) => {}). 2) Promises: Chain-able operations with .then() and .catch(). Example: fetch('url').then(res => res.json()). 3) Async/Await: Syntactic sugar over promises for cleaner code. Example: async function getData() { const response = await fetch('url'); return response.json(); }. Async/await provides better error handling and code readability compared to callbacks and raw promises.

3. What is the microtask queue and how does it relate to the event loop?

Advanced

The microtask queue handles high-priority tasks like Promise callbacks and process.nextTick. Characteristics: 1) Processes before the next event loop phase, 2) Higher priority than macrotasks (setTimeout, setInterval), 3) Includes Promise callbacks and process.nextTick callbacks. Example: process.nextTick(() => console.log('1')); Promise.resolve().then(() => console.log('2')); setTimeout(() => console.log('3'), 0); // Output: 1, 2, 3

4. How do you handle errors in asynchronous operations?

Moderate

Error handling in async operations can be done through multiple patterns: 1) Callbacks: Use error-first pattern. Example: fs.readFile('file.txt', (err, data) => { if (err) handle(err); }). 2) Promises: Use .catch() or try/catch with async/await. Example: async function readFile() { try { const data = await fs.promises.readFile('file.txt'); } catch (err) { handle(err); } }. 3) Event emitters: Use error event handlers. Example: stream.on('error', (err) => handle(err));

5. What is the purpose of the EventEmitter class in Node.js?

Moderate

EventEmitter implements the Observer pattern for event-driven programming. Features: 1) Register event listeners, 2) Emit events, 3) Handle events asynchronously, 4) Multiple listeners per event. Example: const EventEmitter = require('events'); class MyEmitter extends EventEmitter {} const myEmitter = new MyEmitter(); myEmitter.on('event', (data) => console.log(data)); myEmitter.emit('event', 'Hello World');

6. How does Node.js handle CPU-intensive tasks without blocking the event loop?

Advanced

Node.js provides several strategies for CPU-intensive tasks: 1) Worker Threads: Parallel execution of CPU tasks. Example: const { Worker } = require('worker_threads'); const worker = new Worker('./worker.js'); 2) Child Processes: Separate Node.js processes. Example: const { fork } = require('child_process'); const child = fork('cpu_task.js'); 3) Chunking: Breaking large tasks into smaller ones. Example: function processChunk(data, callback) { setImmediate(() => { /* process chunk */ callback(); }); }

7. What are the best practices for handling Promise chains?

Moderate

Best practices for Promise chains include: 1) Always return values in .then(), 2) Use single catch at the end, 3) Avoid nesting promises, 4) Use Promise.all() for parallel operations, 5) Handle rejections properly. Example: fetchUser(id).then(user => { return fetchPosts(user.id); }).then(posts => { return processPosts(posts); }).catch(error => { handleError(error); });

8. How do you implement custom async iterators in Node.js?

Advanced

Custom async iterators can be implemented using Symbol.asyncIterator: Example: class AsyncRange { constructor(start, end) { this.start = start; this.end = end; } async *[Symbol.asyncIterator]() { for(let i = this.start; i <= this.end; i++) { await new Promise(resolve => setTimeout(resolve, 1000)); yield i; } } } async function iterate() { for await (const num of new AsyncRange(1, 3)) { console.log(num); } }

9. What is the difference between parallel and concurrent execution in Node.js?

Advanced

Key differences: 1) Parallel: Multiple tasks execute simultaneously (Worker Threads, Child Processes), 2) Concurrent: Tasks progress simultaneously but execute on single thread (async/await, Promises). Example of parallel: const { Worker } = require('worker_threads'); const workers = [new Worker('./worker.js'), new Worker('./worker.js')]; Example of concurrent: async function concurrent() { const [result1, result2] = await Promise.all([task1(), task2()]); }

10. How do you implement async error handling patterns?

Moderate

Async error handling patterns include: 1) Try-catch with async/await. Example: async function handle() { try { await riskyOperation(); } catch (err) { handleError(err); } } 2) Error boundaries: class ErrorBoundary extends EventEmitter { async execute(fn) { try { return await fn(); } catch (err) { this.emit('error', err); } } } 3) Error-first callbacks: function operation(callback) { doAsync((err, result) => callback(err, result)); }

11. How does Node.js handle timer functions internally?

Advanced

Node.js timer functions work through: 1) Timer phase in event loop, 2) Min heap data structure for efficient timer management, 3) Internal scheduling using libuv. Example: const start = Date.now(); setTimeout(() => console.log(Date.now() - start), 1000); // Actual delay might be longer due to event loop phases and CPU load. setTimeout and setInterval are not exact timing mechanisms.

12. What are async hooks in Node.js and how are they used?

Advanced

Async hooks track lifecycle of async operations: 1) init: Resource creation, 2) before: Callback execution start, 3) after: Callback completion, 4) destroy: Resource cleanup. Example: const async_hooks = require('async_hooks'); const hook = async_hooks.createHook({ init(asyncId, type) { console.log(`${type}: ${asyncId}`); }, destroy(asyncId) { console.log(`Destroyed: ${asyncId}`); } }).enable();

13. How do you implement custom promises in Node.js?

Advanced

Custom promises can be implemented using the Promise constructor: Example: function customPromise(value) { return new Promise((resolve, reject) => { if (value) { setTimeout(() => resolve(value), 1000); } else { reject(new Error('Invalid value')); } }); } class AsyncOperation { static async execute() { return new Promise((resolve, reject) => { // Async operation logic }); } }

14. What are the different phases of Promise execution?

Moderate

Promise execution phases include: 1) Pending: Initial state, 2) Fulfilled: Successful completion, 3) Rejected: Error state. Methods: .then() for fulfillment, .catch() for rejection, .finally() for cleanup. Example: new Promise((resolve, reject) => { doAsync() }).then(result => { // Fulfilled }).catch(error => { // Rejected }).finally(() => { // Cleanup });

15. How do you implement throttling and debouncing in Node.js?

Moderate

Throttling and debouncing control function execution frequency: 1) Throttle: Limit execution rate. Example: function throttle(fn, delay) { let last = 0; return function(...args) { const now = Date.now(); if (now - last >= delay) { last = now; return fn.apply(this, args); } }; } 2) Debounce: Delay execution until pause. Example: function debounce(fn, delay) { let timeoutId; return function(...args) { clearTimeout(timeoutId); timeoutId = setTimeout(() => fn.apply(this, args), delay); }; }

16. How do you handle race conditions in async operations?

Advanced

Race conditions can be handled through: 1) Promise.race() for first completion, 2) Mutex implementation for synchronization, 3) Atomic operations, 4) Proper state management. Example: class Mutex { constructor() { this.locked = false; this.queue = []; } async acquire() { return new Promise(resolve => { if (!this.locked) { this.locked = true; resolve(); } else { this.queue.push(resolve); } }); } release() { if (this.queue.length > 0) { const next = this.queue.shift(); next(); } else { this.locked = false; } } }

17. Explain the concept of event loop starvation and how to prevent it.

Advanced

Event loop starvation occurs when CPU-intensive tasks block the event loop from processing other events. Prevention methods include: 1) Breaking long tasks into smaller chunks using setImmediate, 2) Using Worker Threads for CPU-intensive work, 3) Implementing proper concurrency controls. Example: function processArray(arr) { let index = 0; function nextChunk() { if (index < arr.length) { let chunk = arr.slice(index, index + 1000); // Process chunk setImmediate(() => nextChunk()); // Schedule next chunk index += 1000; } } nextChunk(); }

18. How do you implement cancellable promises in Node.js?

Advanced

Cancellable promises can be implemented using: 1) AbortController for fetch operations, 2) Custom cancel tokens, 3) Wrapper classes with cancel functionality. Example: class CancellablePromise { constructor(executor) { this.abortController = new AbortController(); this.promise = new Promise((resolve, reject) => { executor(resolve, reject, this.abortController.signal); }); } cancel() { this.abortController.abort(); } } const operation = new CancellablePromise((resolve, reject, signal) => { signal.addEventListener('abort', () => reject(new Error('Cancelled'))); });

19. What are the patterns for handling concurrent database operations?

Advanced

Patterns for concurrent database operations include: 1) Connection pooling, 2) Transaction management, 3) Batch operations, 4) Rate limiting. Example: class DBOperations { constructor(pool) { this.pool = pool; } async batchInsert(records, batchSize = 1000) { for (let i = 0; i < records.length; i += batchSize) { const batch = records.slice(i, i + batchSize); await Promise.all(batch.map(record => this.insert(record))); } } async transaction(operations) { const client = await this.pool.connect(); try { await client.query('BEGIN'); const results = await Promise.all(operations.map(op => op(client))); await client.query('COMMIT'); return results; } catch (e) { await client.query('ROLLBACK'); throw e; } finally { client.release(); } } }

20. How do you implement retry mechanisms for async operations?

Moderate

Retry mechanisms can be implemented using: 1) Exponential backoff, 2) Maximum retry limits, 3) Retry delay calculation, 4) Error type checking. Example: async function retry(operation, maxRetries = 3, delay = 1000) { for (let i = 0; i < maxRetries; i++) { try { return await operation(); } catch (error) { if (i === maxRetries - 1) throw error; const waitTime = delay * Math.pow(2, i); await new Promise(resolve => setTimeout(resolve, waitTime)); } } }

21. What are the strategies for handling memory leaks in async operations?

Advanced

Memory leak prevention strategies include: 1) Proper event listener cleanup, 2) Closing resources (files, connections), 3) Monitoring reference counts, 4) Using WeakMap/WeakSet. Example: class ResourceManager { constructor() { this.resources = new WeakMap(); } async useResource(key, resource) { try { this.resources.set(key, resource); await resource.process(); } finally { resource.close(); // Cleanup this.resources.delete(key); } } }

22. How do you implement async iterators for custom data sources?

Advanced

Async iterators can be implemented using Symbol.asyncIterator: Example: class DataSource { constructor(data) { this.data = data; } async *[Symbol.asyncIterator]() { for (const item of this.data) { await new Promise(resolve => setTimeout(resolve, 100)); yield item; } } } async function processData() { const source = new DataSource([1, 2, 3]); for await (const item of source) { console.log(item); } }

23. What are the patterns for implementing rate limiting in async operations?

Advanced

Rate limiting patterns include: 1) Token bucket algorithm, 2) Sliding window, 3) Fixed window counting, 4) Leaky bucket algorithm. Example: class RateLimiter { constructor(limit, interval) { this.limit = limit; this.interval = interval; this.tokens = limit; this.lastRefill = Date.now(); } async acquire() { const now = Date.now(); const timePassed = now - this.lastRefill; this.tokens += Math.floor(timePassed / this.interval) * this.limit; this.tokens = Math.min(this.tokens, this.limit); this.lastRefill = now; if (this.tokens <= 0) { throw new Error('Rate limit exceeded'); } this.tokens--; return true; } }

24. How do you handle timeouts in async operations?

Moderate

Timeout handling includes: 1) Promise race with timeout promise, 2) AbortController integration, 3) Cleanup on timeout. Example: function withTimeout(promise, timeout) { const timeoutPromise = new Promise((_, reject) => { setTimeout(() => reject(new Error('Operation timed out')), timeout); }); return Promise.race([promise, timeoutPromise]); } async function fetchWithTimeout(url, timeout = 5000) { const controller = new AbortController(); const id = setTimeout(() => controller.abort(), timeout); try { const response = await fetch(url, { signal: controller.signal }); clearTimeout(id); return response; } catch (err) { clearTimeout(id); throw err; } }

25. How do you implement async dependency injection?

Advanced

Async dependency injection patterns include: 1) Factory functions, 2) Async constructors, 3) Dependency containers. Example: class Container { constructor() { this.dependencies = new Map(); } async register(key, factory) { this.dependencies.set(key, factory); } async resolve(key) { const factory = this.dependencies.get(key); if (!factory) throw new Error(`No dependency found for ${key}`); return await factory(); } } class Service { static async create(container) { const dependency = await container.resolve('dependency'); return new Service(dependency); } }

26. What are the patterns for handling distributed events in Node.js?

Advanced

Distributed event patterns include: 1) Message queues, 2) Pub/sub systems, 3) Event buses, 4) Webhook implementations. Example: class DistributedEventEmitter { constructor(redis) { this.redis = redis; this.handlers = new Map(); this.redis.subscribe('events'); this.redis.on('message', (channel, message) => { const event = JSON.parse(message); const handlers = this.handlers.get(event.type) || []; handlers.forEach(handler => handler(event.data)); }); } on(eventType, handler) { const handlers = this.handlers.get(eventType) || []; handlers.push(handler); this.handlers.set(eventType, handlers); } emit(eventType, data) { this.redis.publish('events', JSON.stringify({ type: eventType, data })); } }

27. How do you implement async middleware patterns?

Advanced

Async middleware patterns include: 1) Pipeline pattern, 2) Chain of responsibility, 3) Composition pattern. Example: class MiddlewareChain { constructor() { this.middlewares = []; } use(middleware) { this.middlewares.push(middleware); return this; } async execute(context) { return this.middlewares.reduce((promise, middleware) => { return promise.then(() => middleware(context)); }, Promise.resolve()); } } const chain = new MiddlewareChain(); chain.use(async (ctx) => { ctx.validated = true; }).use(async (ctx) => { if (ctx.validated) ctx.processed = true; });

28. What are the strategies for handling backpressure in async streams?

Advanced

Backpressure handling strategies include: 1) Implementing pause/resume mechanisms, 2) Buffer size limits, 3) Throttling, 4) Flow control. Example: class ThrottledStream extends Readable { constructor(source, rate) { super(); this.source = source; this.rate = rate; this.lastRead = Date.now(); } _read(size) { const now = Date.now(); const timeSinceLastRead = now - this.lastRead; if (timeSinceLastRead < this.rate) { setTimeout(() => this._read(size), this.rate - timeSinceLastRead); return; } this.lastRead = now; const chunk = this.source.read(size); this.push(chunk); } }

29. How do you implement async error boundaries?

Advanced

Async error boundaries can be implemented using: 1) Higher-order functions, 2) Class wrappers, 3) Decorator patterns. Example: class AsyncBoundary { constructor(errorHandler) { this.errorHandler = errorHandler; } wrap(target) { return new Proxy(target, { get: (obj, prop) => { const value = obj[prop]; if (typeof value === 'function') { return async (...args) => { try { return await value.apply(obj, args); } catch (error) { return this.errorHandler(error); } }; } return value; } }); } } const safeFetch = new AsyncBoundary(error => console.error(error)) .wrap({ async fetch(url) { const response = await fetch(url); return response.json(); } });

Event Loop & Asynchronous Programming Interview Questions Faq

What types of interview questions are available?

Explore a wide range of interview questions for freshers and professionals, covering technical, business, HR, and management skills, designed to help you succeed in your job interview.

Are these questions suitable for beginners?

Yes, the questions include beginner-friendly content for freshers, alongside advanced topics for experienced professionals, catering to all career levels.

How can I prepare for technical interviews?

Access categorized technical questions with detailed answers, covering coding, algorithms, and system design to boost your preparation.

Are there resources for business and HR interviews?

Find tailored questions for business roles (e.g., finance, marketing) and HR roles (e.g., recruitment, leadership), perfect for diverse career paths.

Can I prepare for specific roles like consulting or management?

Yes, the platform offers role-specific questions, including case studies for consulting and strategic questions for management positions.

How often are the interview questions updated?

Questions are regularly updated to align with current industry trends and hiring practices, ensuring relevance.

Are there free resources for interview preparation?

Free access is available to a variety of questions, with optional premium resources for deeper insights.

How does this platform help with interview success?

Get expert-crafted questions, detailed answers, and tips, organized by category, to build confidence and perform effectively in interviews.