Класс Promise в JavaScript

Класс Promise в JavaScript

В этой статье мы объясняем класс Promise в JavaScript.

YouTube Video

Promise

Класс Promise предназначен для обработки асинхронных операций. Он обрабатывает результаты при успешном завершении операции или ошибки при её сбое. Традиционно использовались функции обратного вызова, когда нужно было дождаться завершения асинхронной операции, но Promise делает этот процесс более понятным и мощным.

1const promise = new Promise((resolve, reject) => {
2    setTimeout(() => resolve("Done!"), 1000);
3});
4
5// Displays "Done!" after 1 second
6promise.then(result => console.log(result));
  • Этот код является примером асинхронного процесса, который выводит «Готово!» через одну секунду.
    • Сначала создаётся новый объект Promise с помощью new Promise. Аргументом является функция, принимающая два обратных вызова: resolve для успешного завершения и reject для ошибки.
    • setTimeout используется для вызова resolve() через одну секунду.
    • Метод then() объекта promise ждёт завершения и выводит результат.

Основная структура

Promise — это объект, который в итоге завершится либо успехом, либо ошибкой.

 1const promise = new Promise((resolve, reject) => {
 2    // Asynchronous operation
 3    // Flag indicating whether the operation was successful
 4    const success = true;
 5
 6    if (success) {
 7        resolve('Operation successful!');
 8    } else {
 9        reject('An error occurred');
10    }
11});
  • В случае успеха вызывается resolve().
  • В случае ошибки вызывается reject().

Объект Promise имеет три состояния.

1promise
2    .then((result) => {
3        console.log(result);
4    })
5    .catch((error) => {
6        console.error(error);
7    })
  • Ожидание
    • Асинхронный процесс еще не завершён.
  • Исполнено
    • Асинхронный процесс успешно завершён, результат возвращён с помощью resolve(). Результат получен с помощью метода then().
  • Отклонено
    • Асинхронный процесс завершился с ошибкой, и возникла ошибка через reject(). Ошибка получена с помощью метода catch().

Методы then() и catch()

С помощью Promise можно определить, что делать при завершении асинхронной операции. Для этого используются методы then() и catch().

then()

1const promise = new Promise((resolve, reject) => {
2    resolve('Operation successful!');
3});
4
5promise.then((result) => {
6    console.log(result);  // "Operation successful!"
7});
  • Метод then() определяет функцию, которая будет вызвана при успешном выполнении Promise.

catch()

1const promise = new Promise((resolve, reject) => {
2    reject('An error occurred');
3});
4
5promise.catch((error) => {
6    console.error(error);  // "An error occurred"
7});
  • Метод catch() определяет функцию, которая будет вызвана при сбое Promise.

Метод finally()

 1const promise = new Promise((resolve, reject) => {
 2    resolve('Operation successful!');
 3});
 4
 5promise
 6    .then((result) => {
 7        console.log(result);
 8    })
 9    .catch((error) => {
10        console.error(error);
11    })
12    .finally(() => {
13        console.log('The operation has completed');
14    });
  • Метод finally() определяет код, который будет выполнен в конце, независимо от того, завершился ли Promise успешно или с ошибкой.

Цепочка then()

then() возвращает новый объект Promise, поэтому вы можете сцеплять следующий then().

 1const promise = new Promise((resolve, reject) => {
 2    setTimeout(() => {
 3        resolve(1);
 4    }, 1000);
 5});
 6
 7promise
 8    .then(result => {
 9        console.log(result); // 1
10        return result + 1;
11    })
12    .then(result => {
13        console.log(result); // 2
14        return result + 1;
15    })
16    .then(result => {
17        console.log(result); // 3
18    })
19    .catch(error => {
20        console.error(error.message); // Something went wrong
21    });
  • В этом коде исходный resolve() передает значение 1, и каждое значение, возвращаемое в then, передается следующему then.
  • Используя catch(), вы можете обработать любую ошибку, возникшую в цепочке, в одном месте.

Практический пример

Например, Promise часто используется для получения данных с сервера. Давайте рассмотрим пример с использованием API fetch().

 1fetch('https://codesparklab.com/json/example.json')
 2    .then(response => {
 3        if (!response.ok) {
 4            throw new Error('Network error');
 5        }
 6        return response.json();
 7    })
 8    .then(data => {
 9        console.log(data);
10    })
11    .catch(error => {
12        console.error('Error:', error);
13    });
  • В этом коде, так как fetch() возвращает Promise, используется then() для обработки данных после получения ответа от сервера. Ошибки обрабатываются с помощью catch().

Обработка нескольких Promises

Promise.all()

Для одновременного выполнения нескольких Promise и продолжения только в случае их успешного выполнения используйте Promise.all().

 1const promise1 = Promise.resolve(1);
 2const promise2 = Promise.resolve(2);
 3const promise3 = Promise.resolve(3);
 4
 5Promise.all([promise1, promise2, promise3])
 6    .then((results) => {
 7        console.log(results);  // [1, 2, 3]
 8    })
 9    .catch((error) => {
10        console.error('Error :', error);
11    });
  • then() вызывается только в случае успешного выполнения всех Promise. catch() вызывается, если хотя бы один из Promise завершится с ошибкой.

Promise.allSettled()

Если вы хотите запустить несколько промисов одновременно и получить все результаты, независимо от успеха или неудачи, используйте Promise.allSettled().

 1const promise1 = Promise.resolve(1);
 2const promise2 = Promise.reject("Failed");
 3const promise3 = Promise.resolve(3);
 4
 5Promise.allSettled([promise1, promise2, promise3])
 6    .then((results) => {
 7        results.forEach(result => console.log(result));
 8        // [
 9        //   { status: 'fulfilled', value: 1 },
10        //   { status: 'rejected', reason: 'Failed' },
11        //   { status: 'fulfilled', value: 3 }
12        // ]
13    });
  • then() вызывается, когда все промисы завершились (либо успешно, либо с ошибкой). Каждый результат содержит свойство status ('fulfilled' или 'rejected'). Даже если некоторые завершаются с ошибкой, это не влияет на другие операции.

Promise.race()

Promise.race() возвращает результат того Promise, который завершится первым, независимо от того, был ли он исполнен или отклонён.

1const promise1 = new Promise((resolve) => setTimeout(resolve, 100, 'First'));
2const promise2 = new Promise((resolve) => setTimeout(resolve, 500, 'Second'));
3
4Promise.race([promise1, promise2]).then((result) => {
5    console.log(result);  // "First"
6});
  • Как и в этом примере, результат первого завершённого Promise возвращается.

Связь с async/await

Использование синтаксиса async/await позволяет писать Promise более интуитивно. async-функция всегда возвращает Promise, а await ожидает её выполнения.

 1async function fetchData() {
 2    try {
 3        const response = await fetch('https://codesparklab.com/json/example.json');
 4        const data = await response.json();
 5        console.log(data);
 6    } catch (error) {
 7        console.error('Error :', error);
 8    }
 9}
10
11fetchData();

Используя async/await таким образом, можно записывать асинхронные операции как синхронный код, что делает его проще для чтения.

Резюме

  • Promise — это объект для обработки успешного выполнения или ошибки асинхронных операций.
  • Успешные операции обрабатываются с помощью then(), а ошибки — с помощью catch().
  • finally() позволяет определить код, который выполняется в конце, независимо от успеха или ошибки.
  • Вы можете обрабатывать несколько Promise одновременно, используя Promise.all() или Promise.race().
  • async/await — это синтаксис для упрощённого написания работы с Promise.

Вы можете следовать этой статье, используя Visual Studio Code на нашем YouTube-канале. Пожалуйста, также посмотрите наш YouTube-канал.

YouTube Video