Куда попадают асинхронные задачи в Dart?

«Куда попадают асинхронные задачи в Dart?» — вопрос из категории Асинхронность, который задают на 29% собеседований Flutter Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Асинхронные задачи в Dart планируются и выполняются Event Loop'ом, который управляет двумя очередями:

  1. Очередь микрозадач (Microtask Queue) — для задач с высшим приоритетом, которые должны выполниться как можно скорее, до следующей задачи из очереди событий.
  2. Очередь событий (Event Queue) — для стандартных асинхронных операций: таймеров (Future.delayed), ввода-вывода (сеть, файлы), взаимодействия с UI, и задач, созданных через Future(() => ...).

Порядок выполнения на практике:

void demonstrateEventLoop() async {
  print('1. Синхронный код выполняется сразу');

  Future(() => print('6. Задача из Event Queue (обычный Future)'));

  scheduleMicrotask(() => print('3. Микрозадача 1'));

  Future.microtask(() => print('4. Микрозадача 2'));

  Future.delayed(Duration.zero, () => print('5. Future с нулевой задержкой тоже в Event Queue'));

  print('2. Синхронный код продолжается');

  // Вывод будет: 1, 2, 3, 4, 5, 6
}

Как это влияет на разработку в Flutter:

  • scheduleMicrotask полезен, когда нужно отложить выполнение кода, но гарантировать, что он выполнится до следующего кадра отрисовки или обработки пользовательского ввода.
  • Опасность блокировки: Длительная синхронная операция внутри микрозадачи заблокирует обработку событий (включая отрисовку UI), что приведёт к "зависанию" интерфейса.
  • Правило: Тяжёлые вычисления лучше выносить в изолят (Isolate) или, как минимум, в обычную очередь событий через Future, чтобы не блокировать цикл обработки микрозадач.