← Bytedance Interview Insights

Bytedance·Frontend Engineer·Technical Phone Screen·Intermediate

IntermediatePrefer not to say
Apr 2026Remote

Summary

Bytedance frontend interview that was basically a deep dive on the JavaScript event loop. Not a broad interview at all, just one topic but they went pretty far into it.

Questions Asked (3)

Q1

Walk me through how JavaScript's single-threaded execution model works, including the call stack, macrotask queue, and microtask queue.

Technical Trade-offsSystem Design
Author's notes

I knew the broad strokes but stumbled a bit on the ordering rules.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by defining JavaScript's single-threaded nature and the event loop as the core mechanism. Then, walk through the call stack, macrotask queue, and microtask queue with a concrete example to illustrate their interaction. Conclude by explaining how this model enables non-blocking I/O and asynchronous behavior.

Pro tip: Emphasize the priority of microtasks over macrotasks and how this affects rendering and user experience. Mention that understanding this is crucial for debugging async code and optimizing performance in frameworks like React.

1. Define single-threaded execution

Explain that JavaScript runs on a single thread, meaning it can execute one piece of code at a time. This simplifies concurrency but requires asynchronous patterns to avoid blocking.

2. Describe the call stack

Detail how the call stack tracks function calls: when a function is invoked, it's pushed onto the stack; when it returns, it's popped. This is where synchronous code executes.

3. Introduce the event loop and queues

Explain that the event loop continuously checks if the call stack is empty. If so, it first processes all microtasks (e.g., Promises, MutationObserver) from the microtask queue, then one macrotask (e.g., setTimeout, I/O) from the macrotask queue.

4. Illustrate with an example

Walk through a code snippet showing the order of execution: synchronous code, then microtasks, then macrotasks. For instance, a setTimeout and a Promise.resolve demonstrate the priority.

5. Connect to real-world implications

Discuss how this model affects UI rendering, event handling, and performance. Mention that long-running synchronous code blocks the event loop, causing unresponsiveness.

Key Points to Mention

  • The call stack executes synchronous code and must be empty before the event loop processes queues.
  • Microtasks (e.g., Promises, queueMicrotask) have higher priority and are executed before the next macrotask.
  • Macrotasks (e.g., setTimeout, setInterval, I/O) are processed one per event loop iteration.
  • The event loop continuously monitors the call stack and queues, enabling non-blocking behavior.
  • Blocking the call stack with heavy synchronous tasks delays both microtasks and macrotasks, affecting responsiveness.
  • Rendering in browsers occurs after microtasks but before the next macrotask, impacting visual updates.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q2

Given a code snippet mixing synchronous code, setTimeout, and Promise.then, what is the execution order and why?

Algorithms & Data StructuresTechnical Trade-offs
Author's notes

This is the classic gotcha and I still second-guessed myself mid-answer.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

First, explain the event loop model: synchronous code runs first, then microtasks (Promise callbacks), then macrotasks (setTimeout). Then walk through the given snippet line by line, categorizing each operation and predicting the output order.

Pro tip: Mention that microtasks are processed until the queue is empty before the next macrotask, and that this can cause starvation if microtasks keep scheduling more microtasks.

1. Identify synchronous code

Scan the snippet for any statements that are not callbacks (e.g., console.log, variable assignments). These execute immediately in order.

2. Identify microtasks

Look for Promise.then, queueMicrotask, or async/await continuations. These are queued as microtasks and run after the current synchronous execution completes.

3. Identify macrotasks

Look for setTimeout, setInterval, setImmediate (Node.js), or I/O callbacks. These are queued as macrotasks and run after all microtasks are drained.

4. Simulate execution order

Walk through the code: run all synchronous code first, then process all microtasks in order, then process the next macrotask (and any microtasks it schedules).

5. Explain the why

Summarize the event loop phases: call stack, microtask queue, macrotask queue, and how the event loop prioritizes microtasks over macrotasks.

Key Points to Mention

  • JavaScript is single-threaded with a call stack and event loop.
  • Microtasks (Promise callbacks) have higher priority than macrotasks (setTimeout).
  • All microtasks are executed before the next macrotask, even if new microtasks are added.
  • setTimeout with 0 delay still waits for all microtasks to complete.
  • The order of scheduling matters: microtasks are processed in FIFO order.
  • Async/await is syntactic sugar over Promises and microtasks.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q3

How does async/await relate to Promises under the hood? What does the runtime actually do when it hits an await expression?

Technical Trade-offsAPI & Integrations
Author's notes

Answered that await is basically syntactic sugar that suspends the function and resumes it as a microtask continuation.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by explaining that async/await is syntactic sugar over Promises, then walk through the runtime mechanics of an await expression: suspension, microtask queue, and resumption. Emphasize that async functions always return a Promise and that await yields control to the event loop, allowing other tasks to run.

Pro tip: Mention that await uses the same microtask queue as Promise.then, so it doesn't block the main thread but can starve rendering if overused. Also note that async/await can be transpiled to generators + Promises, which clarifies the underlying implementation.

1. Define async/await as syntactic sugar

State that async/await is built on Promises and generators, providing a synchronous-looking syntax for asynchronous code. An async function always returns a Promise, and await pauses execution until the Promise settles.

2. Explain the await expression mechanics

When the runtime hits await, it evaluates the expression, wraps it in a Promise (if not already one), and suspends the async function. The function's continuation is scheduled as a microtask to run when the Promise resolves or rejects.

3. Describe the event loop and microtask queue

The suspension yields control back to the event loop, allowing other synchronous code to run. The continuation is queued as a microtask, which runs after the current task and before the next macrotask, ensuring high-priority execution.

4. Contrast with Promise chains

Highlight that await is equivalent to .then() but with cleaner syntax and better stack traces. Both use the microtask queue, but await allows try/catch for error handling and sequential-looking code.

5. Discuss implications and trade-offs

Mention that while await doesn't block the main thread, excessive microtasks can delay rendering. Also note that async/await can be transpiled to generators and Promises, which reveals the underlying implementation.

Key Points to Mention

  • Async functions always return a Promise, even if you don't explicitly return one.
  • Await suspends the async function and schedules its continuation as a microtask.
  • The microtask queue is processed after the current macrotask and before the next, ensuring high-priority execution.
  • Await is essentially equivalent to calling .then() on the awaited value, but with synchronous-looking syntax.
  • Error handling with try/catch in async functions is analogous to .catch() on Promises.
  • Transpilers like Babel convert async/await to generator functions and Promise chains, demonstrating the underlying mechanism.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.