← Назад к вопросам

Что относится к microtask?

2.3 Middle🔥 151 комментариев
#Асинхронность

Комментарии (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

ХарактеристикаMicrotaskMacrotask
ПриоритетОчень высокийНизкий
Примеры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!

Что относится к microtask? | PrepBro