Что относится к микрозадачам (microtask) в Dart?

Ответ

Микрозадачи (microtasks) в Dart — это задачи с высшим приоритетом, которые выполняются сразу после текущего синхронного кода, но перед обработкой следующей макрозадачи из очереди событий (event queue). Они планируются в отдельную очередь микрозадач (microtask queue).

Типичные примеры микрозадач:

  • Явное планирование: Через scheduleMicrotask().
  • Завершение Future: Коллбэк, переданный в Future.microtask().
  • Обработчики then, catchError, whenComplete: Выполняются как микрозадачи, если Future уже завершен (has value) в момент вызова then. Если Future еще в ожидании, то then добавит коллбэк в очередь микрозадач на момент завершения Future.

Зачем это нужно? Микрозадачи позволяют выполнить работу асинхронно, но гарантированно до следующего отрисовки кадра (frame). Это критично для обновления состояния перед рендерингом UI, чтобы избежать "мерцания" или состояния гонки.

Пример использования:

void updateStateAndScheduleRebuild() {
  // Критичное обновление данных, которое должно отразиться в следующем кадре
  _someValue = newValue;

  // Планируем микрозадачу, чтобы уведомить слушателей/перестроить UI
  // ДЕЛАЕТСЯ ДО ЛЮБЫХ ОЖИДАЮЩИХ МАКРОЗАДАЧ (например, таймеров, network response)
  scheduleMicrotask(() {
    _controller.add(newValue); // Уведомление Bloc/Cubit или ChangeNotifier
  });
}

Важное предупреждение: Нельзя блокировать очередь микрозадач долгими операциями. Если добавить туда бесконечный цикл или тяжелую синхронную работу, Event Loop не сможет перейти к обработке событий (тапов, анимаций), и приложение "зависнет".

Ответ 18+ 🔞

Давай разберем эту тему про микрозадачи, а то тут, бля, можно реально на ровном месте приложение повесить, если не въехать.

Представь себе бар. Event Loop — это бармен, очередь событий (event queue) — это стойка, где заказы висят. Макрозадачи — это нормальные заказы: «принеси пива», «сделай бургер». Их бармен разгребает по очереди.

А микрозадачи — это, ёпта, как будто ты сам бармену в ухо шипишь: «Слушай, чувак, пока ты это пиво наливаешь, передай вот этому челу на краю стойки, что его девушка только что ушла с другим. СРОЧНО». Это высший приоритет. Бармен нальёт пиво, но ПЕРЕД тем, как отдать его первому в очереди, он обернётся и шепнёт твоему другу эту новость. Вот и вся магия.

Где эта пакость прячется?

  1. Прямой вызов: scheduleMicrotask(). Сам сказал — сам получил.
  2. Завершённый Future: Future.microtask() или когда ты вызываешь .then() на Future, который УЖЕ выполнился (has value). Коллбэк швырнёт прямиком в эту самую срочную очередь.
  3. А если Future ещё в процессе? Тогда твой .then() просто станет стукачом. Он прицепится к этому Future и, как только тот завершится, КРИКНЕТ в очередь микрозадач: «Эй, пора мой коллбэк выполнять!».

Зачем этот геморрой?

Всё просто, чувак. UI. Чтобы не было этого мерзкого мерцания, когда данные обновились, а виджет ещё старый рисуется. Ты обновил состояние (например, _someValue = 42;), а потом через scheduleMicrotask() говоришь фреймворку: «Бро, перерисуй виджеты, но СЕЙЧАС, ДО того как система возьмётся за следующую анимацию или таймер». Так ты избегаешь состояния гонки, этакой пиздопроебибны, когда всё работает через раз.

Вот, смотри, как это выглядит в коде:

void updateStateAndScheduleRebuild() {
  // Меняем данные синхронно — раз!
  _someValue = newValue;

  // Говорим: "Эй, Event Loop, как только с этим кодом закончишь,
  // ПЕРВЫМ ДЕЛОМ (до любых таймеров или I/O) — выполни вот это!"
  scheduleMicrotask(() {
    _controller.add(newValue); // Кидаем событие в BLoC/Riverpod/ChangeNotifier
  });
}

И теперь, блядь, ГЛАВНОЕ ПРЕДУПРЕЖДЕНИЕ, на котором все обжигаются.

Очередь микрозадач — это не мусорка, куда можно скидывать что попало. Это как очень тонкий лёд. Если ты туда засунь тяжёлую синхронную херню, бесконечный цикл или, ядрёна вошь, операцию на 5 секунд — ты её заблокируешь нахуй. Event Loop не сможет переключиться на обработку нормальных событий: тапов, свайпов, анимаций. Пользователь будет тыкать в экран, а приложение просто повиснет, как будто накрылось медным тазом. Интерфейс будет неотзывчивым, и в консоль полетят гневные ошибки про заморозку кадров.

Короче, запомни: микрозадачи — для быстрых, срочных уведомлений, которые должны вклиниться ПЕРЕД чем-то ещё. Не для вычисления твоей нейросети. Иначе будет тебе не хиросима, а настоящий нигерсраки в продакшене.