Асинхронный JavaScript: как работают колбеки, промисы и async-await

Наши соц. сети: instagram, facebook, telegram

JavaScript позиционирует асинхронное программирование как фичу. Это означает, что если какое-либо действие занимает некоторое время, ваша программа может продолжать выполнять другие действия, пока предыдущее действие завершается. Как только это действие выполнено, ты можешь что-то сделать с результатом. Это будет отличным решением для таких функций, как выборка данных, но это может сбить с толку новичков. В JavaScript у нас есть несколько различных способов справиться с асинхронностью: колбеки, промисы и async-await.

Колбек функции

Функция колбек - это предоставляемая вами функция, которая будет выполняться после завершения асинхронной операции. Давай создадим фейковую функцию для получения пользовательских данных и используем колбек, чтобы что-то сделать с результатом.

Фейковая функция получения данных

Сначала мы создаем фейковуя функция получения данных, которая не принимает колбек. Поскольку fakeData не существует в течение 300 миллисекунд, у нас нет синхронного доступа к ней.

const fetchData = userId => { setTimeout(() => { const fakeData = { id: userId, name: 'George', }; // Our data fetch resolves // After 300ms. Now what? }, 300); }

Чтобы действительно иметь возможность что-то делать с нашими fakeData, мы можем передать fetchData как ссылку на функцию, которая будет обрабатывать наши данные!

const fetchData = (userId, callback) => { setTimeout(() => { const fakeData = { id: userId, name: 'George', }; callback(fakeData); }, 300); };

Давайт создадим базовую функцию колбек и протестируем ее:

const cb = data => { console.log("Here's your data:", data); }; fetchData(5, cb);

Через 300 мс мы увидим следующее:

// Here's your data: {id: 5, name: "George"}

Промисы

Объект Promise представляет возможное завершение операции в JavaScript. Промисы могут быть либо resolve, либо reject (решены или отклонены). Когда Promise разрешается (resolve()), ты можешь обработать его возвращенное значение с помощью метода then. Если Promise отклонено (reject()), ты можешь использовать catch для отлова ошибки и обработать её.

Синтаксис объекта Promise следующий:

new Promise(fn);

Если fn - это функция, которая принимает функцию resolve и, необязательно, функцию reject.

fn = (resolve, reject) => {};​

Функция получения данных (с промисами)

Давай использовать ту же функцию получения данных, что и раньше. Вместо того, чтобы передавать колбек, мы собираемся вернуть новый объект Promise, который разрешится resolve() с данными нашего пользователя через 300 мс. В качестве бонуса мы также можем дать ему небольшой шанс отказаться reject().

const fetchData = userId => { return new Promise((resolve, reject) => { setTimeout(() => { if (Math.random() < 0.1) { reject('Fetch failed!'); } const fakeData = { id: userId, name: 'George', }; resolve(fakeData); }, 300); }); }

Наша новая функция fetchData может использоваться следующим образом:

fetchData(5) .then(user => { console.log("Here's your data:", user); }) .catch(err => { console.error(err); });

Если fetchData успешно разрешается (resolve()) (это будет происходить 90% времени), мы будем регистрировать наши пользовательские данные, как мы это делали с колбеком. Если он будет отклонен (reject()), мы получим console.error сообщение об ошибке, которое мы создали (“Fetch failed!“).

Одна из плюшек промисов - это то, что вы можете создать цепочку промисов, чтобы выполнить последующие промисы. Например, мы могли бы сделать что-то вроде этого:

fetchData(5) .then(user => { return someOtherPromise(user); }) .then(data => { console.log(data); }) .catch(err => { console.error(err); });

Кроме того, мы можем передать массив промисов в Promise.all, чтобы принять меры только после того, как все промисы разрешены (resolve()),то есть все данные получены:

Promise.all([fetchData(5), fetchData(10)]) .then(users => { console.log("Here's your data:", users); }) .catch(err => { console.error(err); });

В этом случае, если оба промиса успешно разрешены (resolve()), будет выведено следующее:

Here's your data:[{ id: 5, name: "George" }, { id: 10, name: "George" }]​

async-await

Async-await предлагает другой синтаксис для написания промисов, которые некоторые считают более понятным. С помощью async-await ты можешь создать асинхронную функцию. Внутри этой асинхронной функции ты можешь дождаться результата Promise перед выполнением следующего кода! Давай посмотрим на наш пример получения данных.

const fetchUser = async userId => { const user = await fetchData(userId); console.log("Here's your data:", user); }; fetchUser(5);

Не плохо, правда? Один маленький ньюансик: мы не рассматриваем наш случай отказа от Promise. Мы можем сделать это с помощью try / catch.

const fetchUser = async userId => { try { const user = await fetchData(userId); console.log("Here's your data:", user); } catch (err) { console.error(err); } }; fetchUser(5);

Надеюсь тебе было полезно😁

Ещё больше полезного в наших соц. сетях instagram, facebook, telegram

Асинхронный JavaScript: как работают колбеки, промисы и async-await
11
Начать дискуссию