Возможно, самая важная концепция в JavaScript — это асинхронность. Эта возможность позволила нам улучшить взаимодействие с пользователем в наших веб-приложениях. Но за кулисами существуют и другие связанные концепции (параллелизм, параллелизм, блокирующее и неблокирующее поведение), которые мы должны сначала понять, прежде чем углубляться в асинхронную модель JavaScript.
Как фронтенд-разработчик, я твердо верю, что вы должны освоить JavaScript (широко известный как Vanilla JavaScript), прежде чем начинать изучать любой из его фреймворков, таких как Vue, Angular или React. Если вы доминируете в JavaScript, вам точно будет легче изучить любой фреймворк.
Несомненно, асинхронность является одной или, возможно, самой важной концепцией, которую разработчик внешнего интерфейса должен освоить, прежде чем начинать работу с любым приложением внешнего интерфейса/JavaScript. Благодаря этой возможности мы можем создавать веб-приложения, выполняющие сложные задачи, где нам нужно запросить любую операцию или ресурс, а затем дождаться ее результата, не влияя на работу пользователя (пользователи ненавидят ждать!). Самый распространенный случай, когда нам нужно получить данные с сервера.
Но какое отношение асинхронность имеет к JavaScript? ну дело в том что:
JavaScript имеет асинхронную неблокирующую модель, в которой цикл обработки событий реализован в одном потоке выполнения.
Асинхронный не... событие... одиночное... что? Позвольте мне разобрать это с самого начала.
Параллелизм и параллелизм
Давайте начнем с пары понятий, которые относятся к способу выполнения некоторых задач. Они часто используются невнятно, но мы можем найти различия, если посмотрим в увеличительное стекло:
Параллелизм — это когда две или более разных задач выполняются одновременно. Эти задачи не обязательно должны выполняться в одно и то же время, и для них требуется один или несколько исполнителей задач (что-то или кто-то, кто выполняет задачу). Да, параллелизм не обязательно означает, что у него должно быть два исполнителя задач.
Метод переплетения является примером параллелизма с одним исполнителем задач, который разбивает задачи на более мелкие задачи и чередует их, так что каждая из них будет выполняться в течение короткого времени. Однако в долгосрочной перспективе создается впечатление, что все они развиваются одновременно.
Параллелизм — это когда две или более разных задач выполняются одновременно и требуют как минимум двух или более исполнителей задач. Мы можем рассматривать параллелизм как частный случай параллелизма.
Представьте себе небольшой ресторан, где его уникальный шеф-повар (таск-раннер) получает заказы (задачи) на приготовление трех блюд. Он решает начать готовить три вида мяса, затем нарезает все овощи для трех салатов и, наконец, готовит картофель. Шеф-повар одновременно работал над тремя блюдами, или три блюда были приготовлены последовательно, но одновременно.
Представьте теперь второй сценарий, когда в ресторане два повара готовят два блюда, и каждый повар работает над мясом, салатом и картофелем для каждого блюда. Тогда мы можем сказать, что два приема пищи готовились параллельно.
A не является одновременным или параллельным, это просто последовательное выполнение. C работает одновременно с одним потоком (переплетается). B и D — это параллелизм.
Операции, связанные с процессором, и операции, связанные с вводом-выводом
Обычно задачи, не требующие внешних ресурсов, выполняются в контексте нашего приложения, в нашем браузере (в области внешнего интерфейса), на нашем ПК, они известны как привязанные к процессору.
Однако есть и другие задачи, в которых нам приходится запрашивать вещи из внешнего источника. Например: получение информации из файла на жестком диске или из базы данных или даже из Интернета. Это задачи, которые выполняются и завершаются вне контекста нашего приложения, которому приходится ждать результата. Они известны как связанные с вводом/выводом (ввод/вывод).
В последней аналогии шеф-повар связан вводом-выводом, когда ему приходится ждать специального ингредиента, предоставленного внешним поставщиком, который должен импортировать его из другого округа, прежде чем ресторан сможет предложить блюдо с этим ингредиентом.
Затем мы говорим, что задачи, связанные с ЦП, являются синхронными, то есть следующая задача не может быть выполнена до тех пор, пока текущая задача не будет завершена. Однако все по-другому для задач, которые находятся вне контроля приложения, когда неизвестно, когда внешний исполнитель задач предоставит ответ, и приложение должно его ждать.
Ввод/вывод: блокировка против неблокировки
…и приложение должно ждать его. Мы пришли к выводу, что задачи, связанные с вводом-выводом, проходят две фазы: фазы ожидания и фазы выполнения. Именно в фазе ожидания мы говорим о блокировке или неблокировке.
В первом исполнитель задачи блокируется во время выполнения одной задачи, и он должен завершить ее, прежде чем обрабатывать что-либо еще. Можно сказать, что этот исполнитель задач является синхронным одиночным потоком.
Во втором средство запуска задач просто «делегирует» (блокирующую) задачу другому внешнему исполнителю задач, чтобы он был свободен и доступен для (синхронного) продолжения выполнения остальных задач. После завершения выполнения внешней задачи он отправляет уведомление первому исполнителю задачи о том, что делегированная задача завершена, и он может возобновить свой процесс с ответом, как только он будет доступен. Затем мы ссылаемся на этот исполнитель задач как на асинхронный одиночный поток.
Javascript-модель
Этот язык программирования изначально был предназначен для того, чтобы сделать пользовательские интерфейсы более интерактивными как с пользователем, так и с сервером (взаимодействия ввода-вывода), в то время как приложение всегда плавно отображается в браузере.
Обратите внимание, что нормальный поток выполнения кода в JavaScript является синхронным, и это нормально для задач, связанных с ЦП, но если бы задачи, связанные с вводом-выводом, также были синхронными, приложение блокировалось бы каждый раз, когда оно запрашивает и ожидает ответа сервера. . Пользователи не знают о процессе, который происходит за кулисами, они просто замечают, что их браузер зависает, что вызывает путаницу и приводит к ужасному пользовательскому опыту.
Наконец, именно поэтому JavaScript имеет асинхронную неблокирующую модель в одном потоке, реализованную с помощью цикла обработки событий. Цикл событий — это тема, которая уже объяснена другими авторами в Medium.
И вот оно. Я надеюсь, что вы нашли это полезным. Спасибо за чтение.