Решаем популярные задачи с асинхронным кодом на JavaScript: часть вторая
Продолжаем разбирать задачи с асинхронным кодом в JS. В этой статье рассмотрим порядок попадания задач в Event Loop и оптимизацию кода.
6К открытий13К показов
В первой части текста мы вспомнили, как устроен цикл событий и разобрали несколько простых задач на асинхронное программирование на JS. В этой статье преподаватель Elbrus Bootcamp Денис Образцов разберёт более сложные примеры на порядок попадания задач в Event Loop и оптимизацию кода.
Задача первая
Разберём задачу подробно. В первой строке объявляется переменная без присвоения значения, после которой создаётся promise и вывод в консоль значения a. Все перечисленные строки — это синхронный код, поскольку сам по себе promise не является асинхронным.
После этого ей присваивается значение: a = 25. Следующим шагом появляется таймер setTimeout, внутри которого вывод значения переменной в консоль и функция resolve, в которую вкладывается переменная ‘a’ для успешного исполнения promise c задержкой в 100 миллисекунд.
Если предыдущий таймер находился внутри promise, то второй setTimeout написан как отдельная функция. Здесь переменной ‘a’ присваивается новое значение, которое выводится в консоль с задержкой в 100 миллисекунд. На последних трёх строчках — обработка promise через then, которая завершается выводом консоли. Очередность вывода и переменная ‘a’ будут выглядеть следующим образом:
С точки зрения очерёдности самая запутанная часть задачи — promise, внутри которого находится setTimeout. Базово таймер относится к макрозадачам, которые попадают в Call Stack последними и выполняются в последнюю очередь. Поскольку в этой задаче он находится внутри promise — микрозадачи, которая выполняется раньше, — в вывод он попадёт третьим. Сразу после того, как отработал весь синхронный код.
Если говорить о значениях, которые выводятся в консоль, то в первой строке будет undefined, поскольку никакое значение на этом этапе переменной не присвоено. Это произойдёт только в следующей строке. Консоль, которая выполняется во вторую очередь, выдаст значение 25, так как она расположена в конце кода, и к моменту её появления значение переменной уже присвоено. В следующих выводах в консоль выводится значение переменной.
Больше задач и историй студентов — в нашем Telegram-канале @Elbrus Bootcamp
Задача вторая
В этой задаче появляется функция async. Прежде чем приступить к разбору, вспомним, для чего она нужна.
Функция async позволяет работать с асинхронным кодом так, будто он синхронный. Синхронный код не работает с асинхронным, но в пределах функции async возможно сделать вид, что так можно. Для этой задачи важно отметить, что любая async-функция сразу же возвращает promise. В паре с async идёт ключевое слово await, которое буквально означает «дождись». Сама по себе async-функция, как и promise — не является асинхронной.
Перейдём к разбору кода. В первой строке находится функция resolveAfter2Seconds, которая принимает аргумент x, выводит его значение в консоль и возвращает его в promise с задержкой в пять секунд.
Далее следует функция async. Внутри неё — синхронная консоль, за которой следуют две асинхронные функции, которые «дожидаются» своего выполнения через await. Результат их поочередного выполнения попадает в promise, а аргумент x приобретает значение сначала ‘a’, а затем — ‘b’. Затем выводится результат Bye.
В последней строчке функции указан вывод результата. Так как любая async возвращает promise, в return не удастся получить конкретного результата. Вместо него мы получим promise pending — ожидание. Then в последней строчке — обработчик этого pending.
В результате порядок выполнения будет следующим:
Этот код работает медленно: чем больше внутри async-функции add1 вызовов функций resolveAfter2Seconds с ожиданием (await), тем больше времени займёт его выполнение. Если вызовов два, то он будет выполняться 10 секунд. Если их будет 10, ждать придётся почти минуту.
Попробуем переписать код и сократить время ожидания. Поставим все вызовы в очередь без await, чтобы они выполнялись все одновременно за пять секунд:
Теперь мы дожидаемся выполнения всех функций уже в конце и только после этого показываем конечный результат. В результате оптимизации ждать придётся не 20 секунд, а всего пять.
Реклама ООО “Эльбрус Буткемп”
6К открытий13К показов