Javascript выполняет код последовательно, по одной операции за раз (однопоточный), и он не может быть прерван другими задачами (невытесняющий). Асинхронные операции могут заблокировать основной поток выполнения и привести к тому, что приложение перестанет отвечать на запросы.

Promises и Async/Await — мощные методы управления асинхронными операциями в JavaScript. Помимо тесной связи, они имеют разный синтаксис и шаблоны использования.

Обещания:

Промис — это объект, который обеспечивает структурированный способ работы со значениями, которые могут быть недоступны сразу, но будут решены в какой-то момент в будущем либо успешно, либо с ошибкой. Это позволяет основному потоку выполнения продолжать выполнение других задач, пока асинхронная операция выполняется в фоновом режиме.

Обещания указывают:

Промисы могут находиться в одном из трех состояний:

  1. Ожидание. Первоначально обещание находится в состоянии ожидания, пока продолжается асинхронная операция.
  2. Выполнено (разрешено): Когда операция завершается успешно и мы вызываем resolve, обещание переходит в выполненное состояние и сохраняет разрешенное значение.
  3. Отклонено. Если возникает ошибка и мы вызываем reject, обещание переходит в состояние отклонения и сохраняет информацию об ошибке.

По завершении асинхронной операции обещание будет либо выполнено с значением, либо отклонено с ошибкой.

Потребление обещаний:

Чтобы работать с результатом промиса, мы используем метод .then() для присоединения обратного вызова, который будет выполнен после разрешения промиса. Мы также можем использовать метод .catch() для обработки ошибок, если обещание отклонено.

Цепочка обещаний:

Мы можем объединить несколько обработчиков .then() для создания последовательности асинхронных операций. Каждый обработчик .then() получает значение, возвращенное предыдущим, что позволяет нам передавать данные между асинхронными шагами.

// Example using promises
const customPromise = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("Promise Resolved");
    }, 3000);
  });
};

console.log("Starting the Promise");

customPromise()
  .then((data) => {
    console.log(data);
    console.log("First Promise Completed");

    // Chaining another Promise
    return new Promise((resolve) => {
      setTimeout(() => {
        resolve("Second Promise Resolved");
      }, 2000);
    });
  })
  .then((secondData) => {
    console.log(secondData);
    console.log("Second Promise Completed");
  })
  .catch((err) => {
    console.log(err);
  });

// Output order:
// Starting the Promise
// Promise Resolved
// First Promise Completed
// Second Promise Resolved
// Second Promise Completed

Основы обещаний, объясненные на примере дня рождения

Асинхронный/Ожидание:

Async/Await позволяет нам писать асинхронный код более лаконичным и читаемым способом, который выглядит и ведет себя как синхронный код. По сути, это синтаксический сахар, построенный на основе промисов.

В Async/Await мы используем ключевое слово async для объявления асинхронной функции, а внутри этой функции мы можем использовать ключевое слово await для приостановки выполнения до тех пор, пока не будет выполнено обещание.

Async функции неявно возвращают обещания:

Promise.resolve("Hello!");

// Same as:

async function greet() {
return "Hello!"
};

Пример использования Async/Await

// New Promise
const promiseFunction = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("Promise resolved successfully");
      reject("Promise rejected with an error");
    }, 2000);
  });
};

// Async/Await
const asyncFunction = async () => {
  try {
    console.log("Start");
    const result = await promiseFunction();
    console.log(result);
    console.log("End");
  } catch (error) {
    console.log(error);
  }
};

asyncFunction();

// Output order:
// Start
// Promise resolved successfully
// End

Async/Await и Promises – ключевые различия:

Итак, когда что использовать!?

  1. Обещания. Промисы — отличный выбор, когда нам нужен лучший контроль над асинхронными операциями, мы хотим обрабатывать ошибки с помощью .catch() или при работе с библиотеками и API, которые возвращают промисы.
  2. Async/Await: Async/Await рекомендуется для большинства сценариев из-за его удобочитаемости и простоты. Это особенно полезно, когда у нас есть последовательность асинхронных операций, которые зависят друг от друга, поскольку позволяет нам писать код, больше похожий на синхронный код.

Краткое содержание:

Хотя и Promises, и Async/Await необходимы для управления асинхронными операциями, основное различие между ними заключается в читаемости кода и удобстве сопровождения.

С точки зрения производительности, нет существенной разницы между цепочками обещаний и Async/Await, когда дело касается базового выполнения асинхронного кода. Оба метода построены на основе промисов, поэтому имеют схожие характеристики производительности.

Поэтому, выбирая между цепочками обещаний и Async/Await, выбирайте Promises, когда вам нужно больше контроля и гибкости, и выбирайте Async/Await для более чистого и читаемого асинхронного кода, особенно для последовательных операций.

Полезные ссылки: