Введение
Мы знаем что наш код выполняется сверху вниз, каждая следующая операция исполнится только после текущей - это называется синхронное программирование. Но довольно часто нам нужно выполнять “операции с ожиданием”, такие как, например, запрос в сеть, ведь запрос может быть удачным, а может быть не удачным (например статус код 404), и поэтому нам надо дождаться ответа от сервера, чтобы оповестить пользователя об успешности или неуспешности запроса. Проблема в том, что ожидание - это тоже операция, ведь нам надо будет непрерывно проверять не пришел ли нам ответ с сервера, а тк мы знаем, что одномоментно у нас может выполняться только одна задача, то, как вы понимаете, следующие задачи у нас не будут выполняться пока не придёт ответ с сервера, а ответ может приходить долго. Соответственно, из-за ожидания мы просто блокируем всю нашу систему.
Как же нам быть в этой ситуации ? Тут-то нам на помощь и приходит асинхронное программирование.
???? Асинхронное программирование — концепция программирования, при которой мы закидываем процесс ожидания ответа от какого-то сервиса в бекграунд, тем самым не блокируя поток выполнения задач.

Dart, как и, наверное, почти любой другой язык, предоставляет нам возможности не только для синхронного программирования, но и для асинхронного, благодаря таким инструментам как Future и Stream.
Future
Класс Future - наш помощник в создании асинхронных операций.
У Future есть 3 состояния:
Uncompleted - незавершенное, операция ещё не запущена или в процессе выполнения
Completed with result - операция завершена успешно
Completed with error - операция завершена с ошибкой
Пример Future:
import 'dart:async';
Future<String> fetchData() {
// Создаем и возвращаем объект Future
return Future(() async {
// Имитируем получение данных с сервера через 2 секунды
await Future.delayed(Duration(seconds: 2));
// Возвращаем результат
return "Hello World";
});
}
void main() {
fetchData().then((data) {
print('Fetched data: $data');
}).catchError((error) {
print("Error fetching data: $error");
});
}
В этом примере, мы используем конструктор Future
для создания нового объекта Future, который будет запущен асинхронно. Внутри этой функции мы имитируем получение данных с сервера с помощью Future.delayed(Duration(seconds: 2))
. Это задерживает выполнение функции на 2 секунды, имитируя время ожидания ответа от сервера. После этого мы используем ключевое слово return
чтобы вернуть результат "Hello World" и завершить функцию.
Когда вы создаете объект Future, он находится в состоянии ожидания, и вы можете добавить функцию, которая будет выполнена, когда Future завершится. Эта функция называется "callback" или "обработчик", её следует передать в метод then. Но then можно и не использовать.
Если выполнение Future завершается с ошибкой, то можно использовать метод catchError
для обработки исключения, он перехватывает исключения, которые были выброшены в Future
. В этом примере catchError
использован для обработки ошибки и вывода сообщения в консоль. Если бы мы не использовали catchError
, то исключение просто было бы выброшено и программа бы завершилась с ошибкой.
Таким образом, метод catchError
является удобным способом для обработки ошибок в Future и позволяет продолжать выполнение программы в случае ошибки.
async / await
async
/ await
- это синтаксический сахар, который позволяет упростить асинхронный код. Вместо использования then мы можем использовать ключевые слова async
/ await
и вызывать нужные нам функции просто сразу после асинхронного кода. Это позволяет писать более легко читаемый и понятный код. Вот как будет выглядеть код, если мы избавимся от прямого использования Future в примере из прошлого блока:
void main() async {
// Пробуем получить данные
try {
final data = await fetchData();
print('Fetched data: $data');
} catch (error) {
// catch вызывается в случае получения ошибки с блока try
print("Error fetching data: $error");
}
}
Future<String> fetchData() async {
// Имитируем ожидание от сервера
await Future.delayed(Duration(seconds: 2));
// Возвращаем якобы полученные данные
return "Hello World";
}
Event Loop
Event Loop - это вечный цикл, выполняющий все задачи
Event loop обрабатывает как асинхронные, так и синхронные функции. Синхронные функции блокируют выполнение Event loop, пока не будут завершены, в то время как асинхронные функции добавляют задачи в очередь и позволяют Event loop продолжать обрабатывать другие задачи, пока они не будут завершены.
Есть 2 очереди задач: Event и MicroTask
Очередь MicroTask
Используется для очень коротких
действий, которые должны быть выполнены асинхронно
, сразу после завершения какой-либо инструкции перед тем, как передать управление обратно Event Loop
.
Очередь microtasks имеет приоритет над обычными и опустошается первой при каждой итерации эвент лупа. Очередь microtasks редко используется разработчиками.
Очередь Event
Используется для планирования операций, которые получают результат от:
-
внешних событий, таких как
операции ввода/вывода
жесты
рисование
таймеры
потоки
...
Future
Фактически, каждый раз при срабатывании внешнего события, соответствующий код ставится в очередь Event
.
Как только оказывается, что очередь MicroTask
пуста, Event Loop
берёт первую задачу из очереди Event
и исполняет её.
Futures
также обрабатываются с помощью очереди Event
.
Как работает Future в Event Loop ?
Когда очередь доходит до нашего Future, Event Loop берёт функцию computation, которую мы передали в качестве аргумента, закидывает в очередь и, когда до неё доходит очередь, Event Loop просто выполняет её в фоне.
Когда функция выполнилась, то после этого отрабатываются методы then, если код выполнился успешно, или catchError, если код выполнился с ошибкой.
Заключение:
Future - чрезвычайна полезная и обязательная вещь для изучения Flutter программистам, понимание этой темы поможет избежать немалого кол-ва ошибок про работе с асинхронщинной и даст понимание в работе с сервером.
Спасибо за прочтение, жду отзывы и правки, если таковые имеются.
Источники:
PackRuble
Спасибо, достаточно просто для понимания написано. ????
Хотелось бы увидеть примеры в разделе про Event Loop, и в каких ситуациях можно применить microtask.