1.0 Асинхронность. Event Loop, MicroTask и Event в Dart
Для кого эта статья?
Данная статья будет полезна тем, кто знаком с основами Dart и Flutter, и решил начать изучение асинхронности в Dart. Мы планируем серию статей, которая поможет безболезненно погрузиться в эту тему. Это первая часть серии.
Зачем нам многопоточность в однопоточном Dart?
Dart создали как аналог JS однопоточным,так как Вебе все однопоточное, позже же Dart начали использовать как язык для фреймворка Flutter.
Везде кричат про многопоточность в Dart, хотя он не является таковым. Давайте разберемся, почему так происходит.
Как быстро сделать бутерброд, пока загружается страница
Это история про асинхронность - что такое асинхронность?
Синхронный порядок - выполнения кода сверху вниз. Пока чайник не закипит, ты не попьешь чай.
Асинхронные порядок в классическом понятии, это тот самый момент когда мы делаем бутерброд, пока у нас что-то грузится. Таким образом, мы задаем задачу загрузить и продолжаем делать свои дела. Мы экономим нервы и время.
Но в дарт асинхронные операции в чистом виде не работают так, ниже вы узнаете почему, но сейчас объясню по другому. Асинхронность в dart это как написание диплома, сказали что надо сделать, но начнешь ты это делать только потом когда-нибудь, когда освободишься(или не прижмет await).
Все вопросы которые у тебя возникают во время прочтения задавай в комментариях, я же в свое время предполагаю что эта за вопросы и буду их объяснять в этой или следующих статьях :)
Разберем на примере человека механизм выполнения кода в dart
Event Loop (цикл событий) - это обычный человек. Он делает все по очереди по кругу, все, что нужно. У него как у всех нас есть какие-то повседневные дела(синхронные операции), которые он выполняет сразу, а есть также какие-то срочные важные дела(MicroTask), а есть важные или срочные дела(Event).
Event Loop (Цикл событий) - это механизм, который управляет тем, как выполнение кода происходит в Dart. Он работает в бесконечном цикле, непрерывно проверяя очередь событий и выполняя код, связанный с каждым событием. Когда Dart начинает выполнение, Event Loop сначала выполняет синхронные операции, а затем проверяет очередь событий (MicroTask) и затем выполняет обработчики событий(Event).
Цикл обработки событий EventLoop от Dart похож на Javascript тем, что в нем есть две очереди FIFO: «Очередь событий и очередь микрозадач».
MicroTask
MicroTask - это важные срочные дела, которые мы делаем не каждый день. Например, пойти к стоматологу. Обычно такие дела быстрые, иначе они могут отразиться на нашей продуктивности, но без них мы не можем (быстрый ответ на действия пользователя в приложении).
Таким образом, MicroTask позволяет обрабатывать задачи в приоритетном порядке, что может быть полезно, например, для обновления пользовательского интерфейса.
Стоить запомнить что она очень редко используется разработчиками, некоторые же признаются что грубо говоря никогда ей и не пользовались.
Event
Это наши действия, которые связаны с внешними событиями, то есть практически все наши действия (послушать лекцию, поговорить по телефону, загуглить, покушать). Как только нам звонят, мы спешим взять трубку, но если мы заняты, то мы сначала доделаем все дела, а затем возьмем трубку.
Очередь событий (Event queue) содержит все внешние события: ввод-вывод, события мыши, события рисования, таймеры, сообщения между изолятами Dart и так далее. Практически вся асинхронность находится в Event, именно с ней разработчики работают больше всего.
Пример однопоточности в Dart
Допустим, я являюсь человеком. Я хожу на работу, пылесошу, выношу мусор, готовлю, хожу в магазин - все эти действия я заношу в Event Loop. После окончания бытовых дел мне пора ехать на работу.
Когда я еду на работу, у меня ломается машина и она больше не может ехать. Следовательно, создается MicroTask "Починить машину". Но для того, чтобы ее починить, мне нужно позвонить в автосервис, чтобы они приехали и забрали машину, а затем починили. Это пример того, как работают зависящие MicroTask от другой MicroTask. После того, как я закончил важные и срочные дела, я могу посмотреть смс в телефоне и ответить на него(Event).
Как вы можете видеть на рисунке, в каждом цикле событий сначала извлекаются все микрозадачи из очереди микрозадач. После того, как очередь микрозадач пуста, выполняется только первый элемент в очереди событий. Как в очереди микрозадач, так и в очереди событий используется порядок FIFO (Первый вход - первый выход).
Утро
Из этого примера мы видим, что вначале выполняются события Event Loop, затем MicroTask, и затем Event.
void main() {
// Добавляется в Event Loop
print('Встать с кровати');
print('Потянуться');
print('Поставить чайник');
// Добавляется в Event
// Чайник должен закипеть, как только он закипит и мы услышим свист.
Future(() => print('Чайник нагрелся'))
.then((value) => print('Услышать свист чайника'));
// Добавляется в MicroTask
Future.microtask(() => print('Покормить кота'));
}
Мы узнали основные механизмы обеспечения асинхронности в dart. Как мы видим появились какие-то новые для нас слова Future, .then, .micro tasks. Разберем их в следующей статье. Мы советуем дочитать весь цикл статей и затем говорить о его целостности. Расскажите в комментариях как вам статья, примеры?