Асинхронный JavaScript: сила обещаний и async/await

Введение

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

Понимание асинхронных операций

В JavaScript асинхронные операции происходят, когда для выполнения задачи требуется время, например получение данных с сервера, отправка запросов API или чтение файлов. По умолчанию JavaScript выполняет код синхронно, то есть ожидает завершения каждой операции, прежде чем перейти к следующей строке. Однако это может привести к снижению производительности и невосприимчивости пользовательского интерфейса при выполнении трудоемких задач. Асинхронность позволяет нам инициировать операции и продолжать выполнение другого кода, не дожидаясь их завершения.

Представляем обещания

Промисы — это объекты, представляющие возможное завершение или сбой асинхронной операции. Они обеспечивают более структурированный и организованный способ обработки асинхронного кода по сравнению с обратными вызовами. Обещание может находиться в одном из трех состояний: в ожидании, выполнено или отклонено. Когда обещание находится в ожидании, асинхронная операция все еще продолжается. При его выполнении операция завершилась успешно, а при отклонении произошла ошибка. Промисы обеспечивают чистый и структурированный способ обработки асинхронных задач путем объединения таких методов, как .then() и .catch(). Давайте посмотрим на пример:

const fetchData = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('Data fetched successfully!');
  }, 2000);
});

fetchData
  .then((data) => {
    console.log("Success>>>", data);
  })
  .catch((error) => {
    console.log("Error>>>", error);
  });

В приведенном выше фрагменте кода мы создали промис с именем fetchData, который имитирует получение данных с задержкой в ​​2 секунды. Функция resolve() вызывается при успешном выполнении операции, а метод .then() используется для обработки состояния выполнения. При возникновении ошибки вызывается функция reject(), а метод .catch() обрабатывает состояние отклонения.

Использование или использование async/await

Хотя Promises обеспечивает значительное улучшение по сравнению с традиционными подходами на основе обратного вызова, они все же могут привести к сложным и вложенным структурам кода. Здесь на помощь приходит async/await. Синтаксис async/await был введен в ECMAScript 2017 (ES8), чтобы сделать асинхронный код еще более читабельным и лаконичным. async/await — это синтаксический сахар, созданный поверх Promises, который упрощает написание асинхронного кода и управление им. Это позволяет разработчикам писать асинхронный код синхронным образом, что упрощает его чтение и понимание. Ключевое слово async используется для определения асинхронной функции, а ключевое слово await используется для ожидания Promise разрешения или отклонить. Давайте посмотрим на пример:

function fetchData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('Data fetched successfully!');
    }, 2000);
  });
}

async function fetchDataAsync() {
  try {
    const data = await fetchData();
    console.log(data);
  } catch (error) {
    console.log(error);
  }
}

fetchDataAsync();

В этом фрагменте кода мы определяем функцию fetchData(), которая возвращает Promise. Функция fetchDataAsync() помечена как асинхронная и использует ключевое слово await для приостановки выполнения до тех пор, пока не будет выполнено Promise. решено или отклонено. Это позволяет нам писать асинхронный код в более линейном и синхронном стиле.

Обработка ошибок в async/await

Как promises, так и async/await предлагают надежные возможности обработки ошибок. С обещаниями вы можете использовать метод .catch() для обработки ошибок в любой точке цепочки обещаний. Точно так же async/await предоставляет блок try-catch для перехвата и обработки ошибок.

В дополнение к этому async/await упрощает обработку параллельных асинхронных операций с помощью promise.all(). Это позволяет выполнять несколько обещаний одновременно и возвращает новое обещание, которое разрешается, когда все предоставленные промисы разрешаются. Вот пример простого promise.all().

const urls = ['https://test.com/1', 'https://test.com/2', 'https://test.com/3'];

function fetchData(url) {
  return new Promise((resolve, reject) => {
    // Simulating an asynchronous operation with setTimeout
    setTimeout(() => {
      resolve(`Data fetched from ${url}`);
    }, 2000); // delay of 2 seconds
  });
}

const promises = urls.map(url => fetchData(url));

Promise.all(promises)
  .then(results => {
    console.log('All promises resolved...');
    results.forEach(data => {
      // the response for each promise will be in data
      console.log(data);
    });
  })
  .catch(error => {
    console.log('Error occurred:', error);
  });

В приведенном выше фрагменте кода мы объявляем массив URL-адресов, из которых мы хотим получить данные, а затем у нас есть функция fetchData(), которая возвращает обещание. сильный>. Мы сопоставили массив, чтобы инициировать несколько асинхронных операций, каждая из которых вызывает функцию fetchData(). Затем мы используем promise.all(), чтобы дождаться разрешения всех обещаний. В качестве аргумента он принимает массив обещаний. После того, как все промисы разрешены, выполняется обратный вызов .then(), получая массив результатов в том же порядке, что и входные промисы. . В обратном вызове .then() мы перебираем массив результатов и записываем все извлеченные данные в консоль. Если какое-либо из обещаний отклонено, будет активирован обратный вызов .catch(), что позволит вам обработать любые ошибки, которые могут возникнуть во время параллельных асинхронных операций. Используя promise.all(), вы можете эффективно обрабатывать несколько асинхронных операций параллельно и совместно обрабатывать результаты после их разрешения.

Заключение

Ура! Вот и все. Асинхронный JavaScript — фундаментальный аспект современной веб-разработки, обеспечивающий эффективное выполнение кода. Промисы и async/await позволяют разработчикам обрабатывать асинхронные операции, делая код более читабельным и удобным в сопровождении. При использовании promises и async/await важно следовать рекомендациям, таким как правильная обработка ошибок, избегание чрезмерного вложения и использование параллельного выполнения, когда это уместно.

Если статья оказалась для вас полезной, поделитесь ею с коллегами и друзьями.

Спасибо за чтение и счастливого кодирования!