Ответ
Асинхронность в Dart построена вокруг Event Loop, Futures и Streams. Это однопоточная модель, которая не блокирует выполнение на операциях ввода-вывода (I/O).
1. Основные абстракции
Future<T>: Представляет результат отложенной (асинхронной) операции, которая завершится одним значением (или ошибкой) в будущем.Stream<T>: Представляет последовательность асинхронных событий (данных или ошибок) во времени.
2. Event Loop и Очереди
Dart runtime управляет двумя очередями:
- Microtask Queue: Для высокоприоритетных задач (например, завершение
Futureчерезcompleter.complete()). - Event Queue: Для внешних событий (таймеры, I/O, жесты, отрисовка кадров).
Event Loop постоянно работает: сначала выполняет все задачи из Microtask Queue, затем одну задачу из Event Queue, и так по кругу. Это предотвращает «голодание» событий.
3. Практическое использование
С Future и async/await:
Future<String> fetchUserData() async {
// Имитация сетевого запроса.
await Future.delayed(Duration(seconds: 1));
// Имитация декодирования JSON.
return '{"name": "Alice"}';
}
void main() async {
print('Fetching data...');
try {
final jsonString = await fetchUserData(); // Не блокирует поток.
final user = jsonDecode(jsonString);
print('User: ${user['name']}');
} catch (e) {
print('Error: $e');
}
print('This runs after data is fetched.');
}
Работа со Stream:
Stream<int> timedCounter(Duration interval, int maxCount) async* {
int count = 0;
while (count < maxCount) {
await Future.delayed(interval);
yield ++count; // «Выдаем» значение в поток.
}
}
void main() async {
final stream = timedCounter(Duration(seconds: 1), 5);
await for (final count in stream) {
print('Count: $count'); // Печатает 1, 2, 3, 4, 5 с интервалом в секунду.
}
}
4. Параллелизм: Isolates
Для выполнения CPU-интенсивных задач, чтобы не блокировать Event Loop, используются Isolates. Это отдельные потоки выполнения с собственной памятью, общающиеся через передачу сообщений.
void heavyComputation(SendPort sendPort) {
// Долгий расчет в отдельном изоляте.
final result = _calculatePi(100000);
sendPort.send(result);
}
void main() async {
final receivePort = ReceivePort();
await Isolate.spawn(heavyComputation, receivePort.sendPort);
receivePort.listen((message) {
print('Result from isolate: $message');
receivePort.close();
});
}
Итог: Dart использует неблокирующую асинхронную модель на основе событий, что идеально подходит для I/O-задач в Flutter (сеть, файлы, БД), сохраняя интерфейс плавным.