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

Что такое асинхронность?

1.6 Junior🔥 191 комментариев
#Dart#Асинхронность

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

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

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

Асинхронность в программировании

Асинхронность — это подход к выполнению кода, при котором операция запускается, но программа не ждёт её завершения. Вместо этого код продолжает выполняться дальше, а результат обрабатывается когда он готов.

Синхронность vs Асинхронность

Синхронный код:

print('Start');
final data = fetchData(); // Ждём 2 секунды
print(data);
print('End');

// Вывод:
// Start
// (ждём 2 секунды)
// Loaded data
// End

Асинхронный код:

print('Start');
fetchData().then((data) {
  print(data);
});
print('End');

// Вывод:
// Start
// End
// (спустя 2 секунды)
// Loaded data

Проблема синхронности

Если блокировать UI thread синхронной операцией, приложение "зависает":

void onButtonPress() {
  final data = fetchDataSync(); // Зависает на 2 секунды!
  setState(() => this.data = data);
}

Пользователь видит frozen UI и не может взаимодействовать с приложением.

Асинхронность решает эту проблему

void onButtonPress() async {
  final data = await fetchData(); // Не блокирует UI
  setState(() => this.data = data);
}

// UI остаётся responsive

Уровни асинхронности

1. Callback Hell:

fetchUser(userId, (user) {
  fetchPosts(user.id, (posts) {
    fetchComments(posts[0].id, (comments) {
      // Читаемость страдает
    });
  });
});

2. Promise-like (Future):

fetchUser(userId)
  .then((user) => fetchPosts(user.id))
  .then((posts) => fetchComments(posts[0].id))
  .then((comments) => print(comments));

3. async/await (лучше всего):

final user = await fetchUser(userId);
final posts = await fetchPosts(user.id);
final comments = await fetchComments(posts[0].id);
print(comments);

Event Loop: как это работает

print('1. Sync start');

Future(() => print('2. Future'));

print('3. Sync end');

// Вывод:
// 1. Sync start
// 3. Sync end
// 2. Future

Dart использует Event Loop, который выполняет:

  1. Весь синхронный код
  2. Microtasks (Future callbacks)
  3. Macrotasks (I/O, timers)

Параллельные асинхронные операции

// Плохо: последовательно (занимает 6 секунд)
final user = await fetchUser(); // 2 сек
final posts = await fetchPosts(); // 2 сек
final settings = await fetchSettings(); // 2 сек

// Хорошо: параллельно (занимает 2 секунды)
final results = await Future.wait([
  fetchUser(),
  fetchPosts(),
  fetchSettings(),
]);
final user = results[0];
final posts = results[1];
final settings = results[2];

Streams: асинхронность с множеством значений

Eсли Future = одно значение в будущем, то Stream = множество значений во времени.

// Real-time обновления
Stream<ChatMessage> messages = chatRepository.getMessages();

messages.listen((message) {
  print('New message: ${message.text}');
});

Обработка ошибок в асинхронном коде

try {
  final data = await fetchData();
  print(data);
} on TimeoutException catch (e) {
  print('Request timed out');
} on DioException catch (e) {
  print('Network error: ${e.message}');
} catch (e) {
  print('Unknown error: $e');
}

Race Conditions в асинхронности

// Проблема: два запроса одновременно
var lastResult;

void search(String query) async {
  final result = await api.search(query);
  lastResult = result; // Может быть перезаписан!
}

search('flutter');
search('dart');
// Какой результат в lastResult? Непредсказуемо!

// Решение: используйте CancelToken
CancelToken _cancelToken = CancelToken();

void search(String query) async {
  _cancelToken.cancel();
  _cancelToken = CancelToken();
  
  final result = await api.search(
    query,
    cancelToken: _cancelToken,
  );
  setState(() => lastResult = result);
}

Распространённые ошибки

// Ошибка 1: забыли await
final data = fetchData(); // Это Future, а не данные!
print(data); // Instance of 'Future'

// Ошибка 2: не обработали ошибку
await fetchData(); // Если упадёт, упадёт всё

// Ошибка 3: утечка памяти с Streams
Stream stream = someStream();
stream.listen((_) {}); // Забыли отменить подписку!

Лучшие практики

  • Используйте async/await вместо .then()
  • Всегда обрабатывайте ошибки — try-catch
  • Отменяйте подписки — StreamSubscription.cancel()
  • Используйте Future.wait для параллельных операций
  • Избегайте race conditions — используйте CancelToken
  • Профилируйте — асинхронность может затянуть загрузку

Асинхронность — это основа responsive приложений. Без неё Flutter приложение будет зависать при любом сетевом запросе или IO операции.