Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Microtask в Dart/Flutter
Определение
Microtask — это небольшая асинхронная задача в Dart, которая имеет очень высокий приоритет и выполняется раньше обычных задач из event loop'а. Они находятся в отдельной очереди (microtask queue) и обрабатываются перед обработкой макротасков (обычные async операции).
Event Loop в Dart
┌──────────────────────────────────────────────────────┐
│ Event Loop (Dart Runtime) │
│ │
│ ┌────────────────────────────────────────────────┐ │
│ │ 1. Microtask Queue (ОЧЕНЬ высокий приоритет) │ │
│ │ - Futures from .then() │ │
│ │ - scheduleMicrotask() │ │
│ │ - Zone операции │ │
│ └────────────────────────────────────────────────┘ │
│ ▼ │
│ ┌────────────────────────────────────────────────┐ │
│ │ 2. Macrotask Queue (обычные задачи) │ │
│ │ - I/O операции │ │
│ │ - Timer │ │
│ │ - User input │ │
│ │ - UI rendering │ │
│ └────────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────┘
Что относится к Microtask?
1. scheduleMicrotask()
import 'dart:async';
void main() {
print('1. Start');
scheduleMicrotask(() => print('3. Microtask'));
print('2. End');
}
// Output:
// 1. Start
// 2. End
// 3. Microtask
Почему 3 печатается после 2?
- Синхронный код выполняется первым
- После всего синхронного кода → обработка microtask queue
- Затем → macrotask queue
2. Future.then() (важный момент!)
void main() {
print('1. Start');
Future.value(5).then((value) {
print('2. Future.then: $value'); // Это MICROTASK!
});
Timer(Duration(milliseconds: 0), () {
print('3. Timer'); // Это MACROTASK
});
print('4. End');
}
// Output:
// 1. Start
// 4. End
// 2. Future.then: 5 ← выполнилось раньше Timer!
// 3. Timer
Ключевой момент: Future.then() — это microtask, поэтому выполнится раньше Timer'а!
3. Future.microtask()
void main() async {
print('1. Start');
Future.microtask(() => print('2. Microtask directly'));
Timer(Duration.zero, () => print('3. Timer'));
print('4. End');
}
// Output:
// 1. Start
// 4. End
// 2. Microtask directly
// 3. Timer
4. Zone операции
import 'dart:async';
void main() {
final zone = Zone.current;
zone.scheduleMicrotask(() {
print('Zone microtask');
});
print('Sync code');
}
Практический пример: обработка данных
Future<void> processData() async {
print('1. Начало');
// Microtask 1
scheduleMicrotask(() => print('3. Первый microtask'));
// Future — тоже microtask!
Future.value('data').then((value) {
print('4. Future получил: $value');
});
// Macrotask — Timer
Timer(Duration.zero, () => print('5. Timer сработал'));
// Microtask 2
scheduleMicrotask(() => print('6. Второй microtask'));
print('2. Конец синхронного кода');
}
// Output:
// 1. Начало
// 2. Конец синхронного кода
// 3. Первый microtask
// 4. Future получил: data
// 6. Второй microtask
// 5. Timer сработал
Сравнение Microtask vs Macrotask
| Характеристика | Microtask | Macrotask |
|---|---|---|
| Приоритет | Очень высокий | Низкий |
| Примеры | scheduleMicrotask(), Future.then() | Timer, I/O, User input |
| Когда выполняется | После синхрона, ДО макротасков | После всех microtask'ов |
| Частота | Часто | Реже |
| Сложность | Маленькие | Любого размера |
Когда microtask очень важен
Ситуация 1: Отложенное выполнение, но очень скоро
class DataNotifier {
final _listeners = <VoidCallback>[];
String _data = '';
String get data => _data;
set data(String value) {
_data = value;
// Вместо immediate уведомления,
// уведомим в microtask (но раньше Timer'ов!)
for (var listener in _listeners) {
scheduleMicrotask(listener);
}
}
void addListener(VoidCallback callback) {
_listeners.add(callback);
}
}
Ситуация 2: Коллектирование множественных операций
class BatchProcessor {
final _queue = <Function>[];
bool _isScheduled = false;
void add(Function operation) {
_queue.add(operation);
if (!_isScheduled) {
_isScheduled = true;
// Все операции обработаны в одном microtask
scheduleMicrotask(_processBatch);
}
}
void _processBatch() {
final batch = _queue.toList();
_queue.clear();
_isScheduled = false;
for (var op in batch) {
op();
}
}
}
Часто встречаемые microtask'и во Flutter
1. Completer.complete()
void main() {
final completer = Completer<String>();
print('1. Start');
completer.complete('Done'); // Это создает microtask!
completer.future.then((value) {
print('2. Got: $value'); // Microtask выполнится здесь
});
print('3. After');
}
// Output:
// 1. Start
// 3. After
// 2. Got: Done
2. Stream.listen()
void main() {
final controller = StreamController<int>();
controller.stream.listen((value) {
print('Received: $value'); // Microtask
});
controller.add(42); // Это не выполнится синхронно!
print('After add');
}
// Output:
// After add
// Received: 42
3. Future.wait()
Future<void> main() async {
print('1. Start');
await Future.wait([
Future.value(1),
Future.value(2),
]); // Все Future.then() => microtask'и!
print('2. Done');
}
Потенциальные проблемы с microtask'ами
❌ Проблема: Бесконечный цикл microtask'ов
void problematic() {
void schedule() {
scheduleMicrotask(schedule); // Бесконечный цикл!
}
schedule();
// Приложение зависнет, Timer'ы никогда не выполнятся
}
✅ Решение: Ограничить microtask'и
void safe() {
int count = 0;
void schedule() {
if (count++ < 100) {
scheduleMicrotask(schedule);
}
}
schedule();
// Максимум 100 iterations
}
❌ Проблема: Блокировка UI
void badUI() {
for (int i = 0; i < 1000000; i++) {
scheduleMicrotask(() => print(i)); // Слишком много microtask'ов!
}
// UI замерзнет на много времени
}
Практическое применение в Flutter
class TextEditingNotifier extends ValueNotifier<String> {
TextEditingNotifier(String initialValue) : super(initialValue);
void onTextChanged(String newText) {
// Отложим обновление на microtask
// чтобы батч изменения вместе
scheduleMicrotask(() {
value = newText;
_validateInput(newText);
});
}
void _validateInput(String text) {
// Валидация произойдет в том же microtask
print('Validating: $text');
}
}
Итоги
Microtask в Dart:
- Задачи с очень высоким приоритетом
- Выполняются после синхронного кода, но ДО Timer'ов и I/O
- Основные источники:
scheduleMicrotask(),Future.then(),Completer - Используются для отложенного выполнения, но очень скоро
- Осторожно с бесконечными цепочками — можно заблокировать UI
Понимание microtask'ов критично для правильной работы с асинхронным кодом в Dart и Flutter!