Promise в TypeScript: подробное изучение

Promise — основа асинхронного программирования в JavaScript, и TypeScript имеет полную поддержку типов для Promise.

Через обобщённые параметры можно точно указать типы разрешённого и отклонённого значений Promise.


SVG-диаграмма: рабочий процесс Promise Background Title Promise Workflow Creating a Promise Creating a Promise new Promise((resolve, reject) => {...}) Arrow pending Pending Branch: resolve/reject fulfilled ✓ rejected ✗ Bottom section: Methods then() · catch() · finally() Arrow marker

Почему Promise?

В JavaScript многие операции асинхронны, например сетевые запросы, чтение файлов, таймеры и т. д.

Promise предоставляет единый интерфейс асинхронного программирования, упрощая написание и управление асинхронным кодом.

Поддержка обобщённых типов в TypeScript обеспечивает типобезопасность Promise.

Описание концепции:Promise — это объект, представляющий конечный результат асинхронной операции. Он имеет три состояния: pending (в процессе), fulfilled (успешно), rejected (с ошибкой).


Создание Promise

Используйте конструктор Promise для создания Promise, передав функцию-исполнитель.

Пример

// Создайте Promise, используйте обобщённый тип, чтобы указать тип разрешённого значения
// Promise<string> означает, что при успехе возвращается строка
var promise = new Promise<string>(function(resolve, reject) {
    var success = true;
    if (success) {
        // Вызов resolve означает, что операция успешно завершилась; передайте значение результата
        resolve("Успех!");
    } else {
        // Вызов reject означает, что операция завершилась неудачно; передайте ошибку
        reject(new Error("Сбой"));
    }
});

// Используйте then для обработки успешного случая
promise.then(function(value) {
    console.log("Готово: " + value);
})["catch"](function(error) {
    // Используйте catch для обработки случая ошибки
    console.log("Ошибка: " + error.message);
});

Вывод:

Complete: Success!

Объяснение обобщений:Promise<T>T в Promise<T> — это тип значения, когда Promise успешно разрешается. Это позволяет TypeScript выводить тип возвращаемого значения.


Цепочка Promise

Методы then и catch возвращают новый Promise, что позволяет создавать цепочки вызовов.

Пример

// Цепочка вызовов: каждый then возвращает новое значение, которое принимает следующий then
var promise = Promise.resolve(1)
    .then(function(n) {
        // Первый then, n = 1
        return n * 2;  // Возвращает 2
    })
    .then(function(n) {
        // Второй then, n = 2
        return n + 10;  // Возвращает 12
    })
    .then(function(n) {
        // Третий then, n = 12
        console.log("Итоговый результат: " + n);
        return n;
    });

console.log("Цепочка промисов: " + promise);

Вывод:

最终结果: 12
Promise 链: [object Promise]

Цепочка:Каждый then возвращает новый промис, позволяя выполнять несколько асинхронных операций последовательно.


Promise.all

Promise.all ожидает завершения всех промисов и возвращает массив, содержащий все результаты.

Пример

// Создаём три промиса
var p1 = Promise.resolve(1);
var p2 = Promise.resolve(2);
var p3 = Promise.resolve(3);

// Promise.all ожидает завершения всех промисов
// Возвращает массив, содержащий результаты всех промисов
Promise.all([p1, p2, p3]).then(function(results) {
    console.log("Все завершено: " + results);
    // Вычислить сумму
    console.log("Сумма: " + results.reduce(function(a, b) { return a + b; }, 0));
});

Вывод:

全部完成: 1,2,3
总和: 6

Примечание:Если какой-либо Promise завершится с ошибкой, Promise.all немедленно отклонится и не будет ждать завершения других Promise.


Promise.race

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

Пример

// Создать три Promise с разными задержками
var p1 = new Promise(function(resolve) {
    setTimeout(function() { resolve("p1"); }, 100);
});
var p2 = new Promise(function(resolve) {
    setTimeout(function() { resolve("p2"); }, 50);
});
var p3 = new Promise(function(resolve) {
    setTimeout(function() { resolve("p3"); }, 30);
});

// Promise.race возвращает результат первого завершившегося Promise
Promise.race([p1, p2, p3]).then(function(value) {
    console.log("Первый завершился: " + value);
});

Вывод:

最先完成: p3

Сценарии использования:Promise.race часто используется для реализации тайм-аута: соревнование долго выполняющегося Promise с Promise тайм-аута.


Promise.allSettled

Promise.allSettled ожидает, пока все Promise завершатся (успешно или с ошибкой), и возвращает статус и результат каждого Promise.

Пример

// Создаём промисы, один из которых завершится неудачно
var p1 = Promise.resolve("Success");
var p2 = Promise.reject(new Error("Failure"));
var p3 = Promise.resolve("Done");

// Promise.allSettled ждёт, пока все промисы завершатся
// Возвращает статус и значение/причину каждого промиса
Promise.allSettled([p1, p2, p3]).then(function(results) {
    results.forEach(function(result, index) {
        if (result.status === "fulfilled") {
            console.log("Promise " + index + ": " + result.value);
        } else {
            console.log("Promise " + index + ": " + result.reason.message);
        }
    });
});

Вывод:

Promise 0: 成功
Promise 1: 失败
Promise 2: 完成

Различия:Promise.all останавливается сразу при первом сбое; Promise.allSettled ждёт, пока все промисы завершатся.


Аннотации типов Promise

Поддержка обобщений в TypeScript делает объявления типов Promise точными.

Пример

// Определите функцию, возвращающую Promise
// Promise<{ name: string; age: number }> задаёт тип возвращаемого объекта user
function getUser(): Promise<{ name: string; age: number }> {
    return Promise.resolve({ name: "Alice", age: 25 });
}

// async-функция: неявно возвращает Promise
async function main() {
    // await автоматически выводит тип user
    var user = await getUser();
    console.log("Пользователь: " + JSON.stringify(user));
}

main();

Вывод типов:TypeScript автоматически выводит возвращаемый тип Promise на основе обобщённых параметров, что также даёт нам полные подсказки типов в async/await.


Примечания

  • Обобщённые параметры:Всегда указывайте обобщённые параметры для Promise, чтобы уточнить возвращаемый тип
  • Обработка ошибок:Не забывайте использовать catch для обработки ошибок Promise
  • all против allSettled:Используйте allSettled, когда нужны все результаты, и all, когда нужно быстрое завершение с ошибкой.
  • async/await:В современном коде рекомендуется использовать async/await, поскольку синтаксис более лаконичен.

Лучшие практики:Предпочитайте синтаксис async/await; он по-прежнему основан на Promise, но читается как синхронный код.


Итог

Promise — ядро асинхронного программирования в TypeScript.

  • Promise:Контейнер асинхронной операции с тремя состояниями: pending/fulfilled/rejected
  • then/catch:Цепочки для обработки асинхронных результатов
  • Promise.all:Ожидает завершения всех; если хотя бы один завершится с ошибкой, вся операция завершится с ошибкой.
  • Promise.race:Возвращает первый завершившийся результат
  • Promise.allSettled:Ожидает завершения всех и возвращает статус каждого

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

x Другие расширения