Асинхронное программирование сравнительно молодой инструмент, но уже стал популярным в Javascript, C# и Python. Если ранее разработчикам приходилось обращаясь к серверу ждать ответа, чтобы выполнить следующее действие, то сегодня выполнять процессы можно параллельно. Рано или поздно даже junior программистам придется научиться асинхронным возможностям.
От ада в коде до понятных слов
Еще недавно разработчики использовали «колбэки» (callback-скрипт). Код становился монструозным, неудобным и тяжело читаемым. Не случайно результат часто называют «колбэк хелл». Затем в помощь разработчикам пришли «промисы» (promises) — объекты, содержащие состояния ожидания (pending), успешного и неуспешного выполнения (fulfilled и rejected). На них «навешиваются» «колбэки» onFulfilled или onRejected. Использование «промисов» все еще популярно среди программистов любого уровня за счет гибкости.
Однако метод уступает по удобству простым и понятным ключевым словам async и await. Первое — оборачивает возвращаемое значение в «промис», а второе останавливает выполнение для получения результата, но не блокирует остальной код. Использование ключевых слов заметно ускоряет процесс написания и выполнения процессов.
Я бы предостерег начинающих программистов от async и await прямо сейчас. Для начала необходимо изучить базу языка, понять «колбэки» и «промисы». Никто не заставляет вас использовать старые методы, но для общего понимания — это необходимо.
Было-стало
Рассмотрим пример синхронного кода, который делает следующее:
1) запрашивает json со стороннего ресурса, с использованием XMLHttpRequest 2 раза
2) выводит в консоль 10 раз число 1000000;
3) опять запрашивает json со стороннего ресурса, но уже один раз;
4) опять выводит в консоль 10 раз число 1000000;
5) и еще раз запрашивает json со стороннего ресурса;
let url = «https://jsonplaceholder.typicode.com/comments»;//url для запроса данных
let request = new XMLHttpRequest();//объект для обращения к ресурсу
function get(url, n) {//синхронная функция, в которой отправляется запрос на url с индексом n для опознавания функции получаются данные
console.log(«waiting to fetch…», n);//вывод сообщения
request.open(«GET», url, false)//формирование
request.send(null);//и отправление запроса(блокирующая операция)
console.log(«after fetching…», n);//вывод сообщения
console.log(«waiting to get json…», n);//вывод сообщения
const json = JSON.parse(request.responseText);//парсинг данных(блокирующая операция)
console.log(«after getting json…», n);//вывод сообщения
console.log(json);//вывод json данных
}
get(url, 1);//синхронный вызов функции
get(url, 2);//синхронный вызов функции
for (let index = 0; index < 10; index++) {//дополнительные действия
console.log(1000000);//вывод сообщения
}
get(url, 3);//синхронный вызов функции
for (let index = 0; index < 10; index++) {//дополнительные действия
console.log(1000000);//вывод сообщения
}
get(url, 4);//синхронный вызов функции
Теперь рассмотрим аналогичный пример, но уже с асинхронным программированием и использованием функций async и await.
let url = «https://jsonplaceholder.typicode.com/comments»;
async function async_get(url, n) {//асинхронная функция, в которой отправляется запрос на url с индексом n для опознавания функции получаются данные
console.log(«waiting to fetch…», n);//вывод сообщения
const response = await fetch(url);//асинхронный запрос
console.log(«after fetching…», n);//вывод сообщения
console.log(«waiting to get json…», n);//вывод сообщения
const json = await response.json();//асинхронный парсинг
console.log(«after getting json…», n);//вывод сообщения
console.log(json);//вывод json сообщения
}
Делают вызов fetch и response.json неблокирующими основной процесс. Таким образом, в момент await управление передается в другую функцию, которая будет выполняться до тех пор, пока не встретит await уже она.
async_get(url, 1);//асинхронный вызов функции
async_get(url, 2);//асинхронный вызов функции
for (let index = 0; index < 10; index++) {//дополнительные действия
console.log(1000000);//вывод сообщения
}
async_get(url, 3);//асинхронный вызов функции
for (let index = 0; index < 10; index++) {//дополнительные действия
console.log(1000000);//вывод сообщения
}
async_get(url, 4);//асинхронный вызов функции
Вызов функции async_get не блокирует остальную программу. При выполнении второй программы, можно заметить как в консоли будут появляться сообщения из async_get со вторым аргументом 1, 2, 3 и 4 одновременно — программа не будет дожидаться пока закончится выполнение asyc_get(url, 1) перед тем, как выполнить async_get(url, 2), и так далее.
Второй пример выполняется гораздо быстрее. К тому же код выглядит почти полностью также, как и обычный синхронный вариант благодаря ключевым словам.
- Асинхронное программирование на JavaScript: делаем код удобнее и быстрее - 01/11/2021 16:12