Promise в TypeScript: подробное изучение
Promise — основа асинхронного программирования в JavaScript, и TypeScript имеет полную поддержку типов для Promise.
Через обобщённые параметры можно точно указать типы разрешённого и отклонённого значений Promise.
SVG-диаграмма: рабочий процесс Promise
Почему Promise?
В JavaScript многие операции асинхронны, например сетевые запросы, чтение файлов, таймеры и т. д.
Promise предоставляет единый интерфейс асинхронного программирования, упрощая написание и управление асинхронным кодом.
Поддержка обобщённых типов в TypeScript обеспечивает типобезопасность Promise.
Описание концепции:Promise — это объект, представляющий конечный результат асинхронной операции. Он имеет три состояния: pending (в процессе), fulfilled (успешно), rejected (с ошибкой).
Создание 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, что позволяет создавать цепочки вызовов.
Пример
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, который завершится первым (успешно или с ошибкой).
Пример
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<{ 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:Ожидает завершения всех и возвращает статус каждого
x Другие расширенияРекомендация:Используйте синтаксис async/await вместе с Promise, чтобы асинхронный код был и типобезопасным, и легко читаемым.