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

Как работает Event Loop в Dart?

2.0 Middle🔥 222 комментариев
#Dart#Асинхронность

Комментарии (2)

🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Event Loop в Dart

Event Loop (цикл событий) — это механизм, который управляет выполнением асинхронного кода в Dart. Это сердце асинхронного программирования, позволяющее выполнять операции без блокирования главного потока.

Базовое понимание

Dart работает в одном потоке, но может выполнять асинхронный код благодаря Event Loop. Когда ты ждёшь результата Future или Stream, код не блокируется — Event Loop просто переходит к другому коду.

Две очереди: Microtask и Event

// Event Loop имеет две очереди:

// 1. Microtask Queue (высший приоритет)
// - Future.microtask()
// - Future.sync()
// - Вычисления, которые должны выполниться немедленно

// 2. Event Queue (низший приоритет)
// - Future() — обычные Future
// - Timer
// - I/O операции (сеть, файлы)
// - События UI (нажатия кнопок и т.д.)

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

void main() async {
  print('1. Start'); // Sync — выполняется сразу
  
  Future.microtask(() => print('3. Microtask')); // Высший приоритет
  
  Future(() => print('4. Future')); // Низший приоритет
  
  print('2. End'); // Sync — выполняется сразу
}

// Вывод:
// 1. Start
// 2. End
// 3. Microtask
// 4. Future

Поэтапно: как работает Event Loop

Шаг 1: Выполнение синхронного кода

void main() {
  print('1'); // Выполняется сразу
  print('2'); // Выполняется сразу
  print('3'); // Выполняется сразу
  
  // Далее Event Loop берётся за асинхронный код
}

Шаг 2: Обработка Microtask Queue

void main() async {
  Future.microtask(() {
    print('A'); // Обработается из Microtask Queue
  });
  
  Future.microtask(() {
    print('B'); // Обработается из Microtask Queue
  });
  
  Future(() => print('C')); // Останется в Event Queue
}

// Вывод: A, B, C

Шаг 3: Обработка Event Queue

void main() async {
  Future(() => print('1'));
  Future(() => print('2'));
  
  Timer(Duration(seconds: 0), () => print('3')); // Тоже в Event Queue
  
  // Event Loop обрабатывает их по одному
}

Практические примеры

Пример 1: Порядок выполнения

void main() async {
  print('Start');
  
  // Microtask Queue
  Future.microtask(() => print('Microtask 1'));
  Future.microtask(() => print('Microtask 2'));
  
  // Event Queue
  Future(() => print('Future 1'));
  Future(() => print('Future 2'));
  
  // Синхронный код
  await Future(() => print('Async Future'));
  
  print('End');
}

// Вывод:
// Start
// End
// Microtask 1
// Microtask 2
// Async Future
// Future 1
// Future 2

Пример 2: Фактический порядок с await

void main() async {
  print('A');
  
  await Future(() => print('B'));
  
  print('C');
  
  Future.microtask(() => print('D'));
  
  print('E');
}

// Вывод:
// A
// B
// C
// E
// D

Пример 3: Event Loop в Flutter

import 'package:flutter/material.dart';

class MyApp extends StatefulWidget {
  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  void initState() {
    super.initState();
    
    print('1. initState');
    
    // Event Queue — обновит UI после текущего frame
    Future(() {
      print('3. Future — обновление после frame');
      setState(() {});
    });
    
    // Microtask — выполнится до следующего frame
    Future.microtask(() => print('2. Microtask'));
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text('Hello'),
      ),
    );
  }
}

// Вывод:
// 1. initState
// 2. Microtask
// 3. Future — обновление после frame
// [UI обновляется]

Визуально: как работает Event Loop

┌─────────────────────────────────────────────┐
│           Dart Event Loop                   │
├─────────────────────────────────────────────┤
│                                             │
│  1. Выполнить синхронный код               │
│  ├─ print('Start')                         │
│  ├─ await Future(...)                      │
│  └─ print('End')                           │
│                                             │
│  2. Обработать Microtask Queue             │
│  ├─ Future.microtask(() => ...)            │
│  └─ (высший приоритет)                     │
│                                             │
│  3. Обработать Event Queue                 │
│  ├─ Future(() => ...)                      │
│  ├─ Timer                                  │
│  └─ I/O операции                          │
│                                             │
│  4. Вернуться на шаг 1 (новый цикл)        │
│                                             │
└─────────────────────────────────────────────┘

Практические советы

Используй await правильно

// Плохо: Future не ждёшь
future.then((_) => print('Done'));
print('Before'); // Выполнится раньше than print('Done')

// Хорошо: ждём результат
await future;
print('After'); // Выполнится после Future

Избегай блокирования Event Loop

// Плохо: блокирует Event Loop
Future(() => heavyComputation()); // Синхронный код во время

// Хорошо: разбей на части
Future(() async {
  for (int i = 0; i < 1000; i++) {
    await Future.value(); // Пусти Event Loop дышать
    process(i);
  }
});

Event Loop в контексте Flutter

  • Frame — Flutter перерисовывает UI каждые 16ms (60 FPS)
  • Event Loop управляет тем, что выполняется между frames
  • setState() — вызывает перестроение в Event Loop
  • Future — обычно выполняется в следующем frame
  • Microtask — выполняется до перестроения

Понимание Event Loop критично для написания производительного асинхронного кода в Dart и Flutter.

Как работает Event Loop в Dart? | PrepBro