Javascript выполняет код последовательно, по одной операции за раз (однопоточный), и он не может быть прерван другими задачами (невытесняющий). Асинхронные операции могут заблокировать основной поток выполнения и привести к тому, что приложение перестанет отвечать на запросы.
Promises и Async/Await — мощные методы управления асинхронными операциями в JavaScript. Помимо тесной связи, они имеют разный синтаксис и шаблоны использования.
Обещания:
Промис — это объект, который обеспечивает структурированный способ работы со значениями, которые могут быть недоступны сразу, но будут решены в какой-то момент в будущем либо успешно, либо с ошибкой. Это позволяет основному потоку выполнения продолжать выполнение других задач, пока асинхронная операция выполняется в фоновом режиме.
Обещания указывают:
Промисы могут находиться в одном из трех состояний:
- Ожидание. Первоначально обещание находится в состоянии ожидания, пока продолжается асинхронная операция.
- Выполнено (разрешено): Когда операция завершается успешно и мы вызываем
resolve
, обещание переходит в выполненное состояние и сохраняет разрешенное значение. - Отклонено. Если возникает ошибка и мы вызываем
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 – ключевые различия:
Итак, когда что использовать!?
- Обещания. Промисы — отличный выбор, когда нам нужен лучший контроль над асинхронными операциями, мы хотим обрабатывать ошибки с помощью
.catch()
или при работе с библиотеками и API, которые возвращают промисы. - Async/Await: Async/Await рекомендуется для большинства сценариев из-за его удобочитаемости и простоты. Это особенно полезно, когда у нас есть последовательность асинхронных операций, которые зависят друг от друга, поскольку позволяет нам писать код, больше похожий на синхронный код.
Краткое содержание:
Хотя и Promises, и Async/Await необходимы для управления асинхронными операциями, основное различие между ними заключается в читаемости кода и удобстве сопровождения.
С точки зрения производительности, нет существенной разницы между цепочками обещаний и Async/Await, когда дело касается базового выполнения асинхронного кода. Оба метода построены на основе промисов, поэтому имеют схожие характеристики производительности.
Поэтому, выбирая между цепочками обещаний и Async/Await, выбирайте Promises, когда вам нужно больше контроля и гибкости, и выбирайте Async/Await для более чистого и читаемого асинхронного кода, особенно для последовательных операций.