tezvyn:

Explain Dart's event loop, microtask queue, event queue, and await behavior

AI-drafted, machine-checkedSource: dart.devadvanced
Explain Dart's event loop, microtask queue, event queue, and await behavior

Tests Dart single-threaded event loop model. Strong answer: microtasks drain before event queue tasks; await suspends the function and schedules its resumption via the event loop when the Future completes. Red flag: claiming await blocks the thread.

WHAT THIS TESTS: Your grasp of Dart's single-threaded event-driven architecture inside a single isolate. The interviewer wants to know if you understand that Dart concurrency is cooperative rather than preemptive, and that async-await is syntactic sugar over Future callbacks scheduled on the event loop. They are checking whether you can reason about frame jank, timer precision, and microtask starvation.

A GOOD ANSWER COVERS: First, that every isolate has exactly one event loop and two queues: the microtask queue and the event queue. Second, that the event loop's only job is to pick the next task to run, and it always empties the entire microtask queue before looking at the event queue. This means microtasks can starve the event queue if they keep rescheduling themselves. Third, that the event queue contains external events like user input, file I/O completions, and timers, while the microtask queue handles internal short async work such as Future.value resolution and async/await bookkeeping. Fourth, that awaiting a Future splits the async function at the await boundary. The code after await becomes a closure attached to that Future, the function immediately returns an incomplete Future to its caller, and when the awaited Future completes, its continuation is enqueued on the event loop rather than executed instantly. Fifth, that because all of this happens on a single thread per isolate, no two Dart callbacks run in parallel within the same isolate.

COMMON WRONG ANSWERS: Saying that await blocks the thread or pauses the isolate. It does not block; it yields control and the event loop keeps spinning. Claiming that microtasks and event queue tasks interleave one-for-one. They do not; microtasks always batch-drain first. Stating that the rest of the function runs synchronously right after the Future resolves. In reality it is scheduled as an event-loop task. Describing threads instead of isolates. Dart uses isolates, not shared-memory threads, for parallel work.

LIKELY FOLLOW-UPS: How does Future.microtask differ from a normal Future constructor? What happens if a microtask recursively schedules more microtasks? How would you move heavy computation off the main isolate? Why might a Timer.periodic drift when the event loop is busy? How does the event loop relate to Flutter's build, layout, and paint pipeline?

ONE CONCRETE EXAMPLE: Imagine an async function that prints A, awaits a Future.delayed of one second, then prints B. When called, A prints immediately because it runs synchronously up to the await. The await causes the function to return an incomplete Future to its caller. After one second, the timer puts a completion task on the event queue. The event loop eventually picks it up, and the continuation prints B. If you had inserted Future.microtask(() => print C) before the await, C would print before A's function even suspended, because microtasks run before the next event-loop turn.

Source: dart.dev

Read the original → dart.dev

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.