目录
- TypeScript 中的 Promise 和异步操作全解
- ☝️1 什么是 Promise?
- ✌️1.1 创建 Promise
- ☝️2 Promise 的状态
- ☝️3 Promise 的链式操作
- ☝️4 Promise 的组合
- ✌️4.1 `Promise.all`
- ✌️4.2 `Promise.allSettled`
- ✌️4.3 `Promise.race`
- ✌️4.4 `Promise.any`
- ☝️5 使用 `async/await`
- ✌️5.1 基础用法
- ✌️5.2 捕获错误
- ✌️5.3 异步并行
- ☝️6 实战场景
- ✌️6.1 重试机制
- ✌️6.2 超时机制
TypeScript 中的 Promise 和异步操作全解
在现代 JavaScript/TypeScript 开发中,异步操作是一种非常常见的场景,Promise
和 async/await
提供了强大的工具来处理异步逻辑。TypeScript 的类型系统为这些操作增加了安全性和可维护性。本文将从基础到高级,系统性地总结 Promise
和异步操作在 TypeScript 中的用法。
☝️1 什么是 Promise?
Promise
是一种用于处理异步操作的对象,表示一个未来可能完成(resolved)或失败(rejected)的值。
✌️1.1 创建 Promise
const promise = new Promise<number>((resolve, reject) => {const success = true; // 模拟成功或失败if (success) {resolve(42); // 返回成功的值} else {reject(new Error('Something went wrong'));}
});// 使用 then 和 catch
promise.then((value) => {console.log('Resolved:', value); // 输出:Resolved: 42}).catch((error) => {console.error('Rejected:', error.message);});
Promise
的泛型指定resolve
返回值的类型。resolve
用于表示操作成功,reject
用于表示操作失败。
☝️2 Promise 的状态
Promise 有以下三种状态:
- Pending(进行中): 初始状态,既未完成也未失败。
- Fulfilled(已完成): 操作成功,调用了
resolve
。 - Rejected(已失败): 操作失败,调用了
reject
。
☝️3 Promise 的链式操作
Promise 支持链式操作,通过 then
返回新的 Promise。
const promise = new Promise<number>((resolve) => {resolve(10);
});promise.then((value) => {console.log('Step 1:', value); // 输出:Step 1: 10return value * 2; // 返回值会作为下一个 then 的输入}).then((value) => {console.log('Step 2:', value); // 输出:Step 2: 20return value + 5;}).then((value) => {console.log('Step 3:', value); // 输出:Step 3: 25}).catch((error) => {console.error('Error:', error.message);});
☝️4 Promise 的组合
✌️4.1 Promise.all
我的另一篇相关文章:掌握 Promise.all并行处理异步操作
Promise.all
接受一个 Promise
数组,当所有 Promise 完成时返回结果数组。
const promise1 = Promise.resolve(10);
const promise2 = Promise.resolve(20);
const promise3 = Promise.resolve(30);Promise.all([promise1, promise2, promise3]).then((results) => {console.log('All results:', results); // 输出:[10, 20, 30]}).catch((error) => {console.error('Error:', error.message);});
- 如果任何一个 Promise 被拒绝(
rejected
),Promise.all
会立即失败。
✌️4.2 Promise.allSettled
Promise.allSettled
返回每个 Promise 的结果,无论成功还是失败。
const promise1 = Promise.resolve(10);
const promise2 = Promise.reject(new Error('Failed'));
const promise3 = Promise.resolve(30);Promise.allSettled([promise1, promise2, promise3]).then((results) => {console.log('Results:', results);
});
[{ status: 'fulfilled', value: 10 },{ status: 'rejected', reason: Error: Failed },{ status: 'fulfilled', value: 30 }
]
✌️4.3 Promise.race
Promise.race
返回第一个完成的 Promise。
const promise1 = new Promise((resolve) => setTimeout(() => resolve('First'), 500));
const promise2 = new Promise((resolve) => setTimeout(() => resolve('Second'), 1000));Promise.race([promise1, promise2]).then((result) => {console.log('Race result:', result); // 输出:First
});
✌️4.4 Promise.any
Promise.any
返回第一个成功的 Promise,如果所有都失败,则抛出 AggregateError
。
const promise1 = Promise.reject(new Error('Error 1'));
const promise2 = new Promise((resolve) => setTimeout(() => resolve('Success'), 500));
const promise3 = Promise.reject(new Error('Error 2'));Promise.any([promise1, promise2, promise3]).then((result) => {console.log('Any result:', result); // 输出:Success}).catch((error) => {console.error('All failed:', error.errors);});
☝️5 使用 async/await
async/await
是对 Promise 的语法糖,能让异步代码看起来像同步代码。
✌️5.1 基础用法
async function fetchData(): Promise<string> {return 'Hello, Async!';
}async function main() {const data = await fetchData();console.log(data); // 输出:Hello, Async!
}main();
- 使用
async
定义异步函数,返回值为 Promise。 await
用于等待 Promise 的完成。
✌️5.2 捕获错误
使用 try...catch
捕获异步操作中的错误。
async function fetchData(): Promise<string> {throw new Error('Failed to fetch');
}async function main() {try {const data = await fetchData();console.log(data);} catch (error) {console.error('Error:', (error as Error).message); // 输出:Error: Failed to fetch}
}main();
✌️5.3 异步并行
async function fetchValue(value: number, delay: number): Promise<number> {return new Promise((resolve) => setTimeout(() => resolve(value), delay));
}async function main() {const [value1, value2] = await Promise.all([fetchValue(10, 1000),fetchValue(20, 500),]);console.log('Results:', value1, value2); // 输出:Results: 10 20
}main();
☝️6 实战场景
✌️6.1 重试机制
async function fetchWithRetry<T>(fn: () => Promise<T>, retries: number): Promise<T> {for (let i = 0; i <= retries; i++) {try {return await fn();} catch (error) {if (i === retries) throw error;console.log(`Retry ${i + 1}...`);}}throw new Error('Failed after retries');
}async function fetchData(): Promise<string> {if (Math.random() > 0.5) throw new Error('Random failure');return 'Success';
}fetchWithRetry(fetchData, 3).then((result) => console.log(result)).catch((error) => console.error(error.message));
✌️6.2 超时机制
async function fetchWithTimeout<T>(promise: Promise<T>, timeout: number): Promise<T> {const timeoutPromise = new Promise<T>((_, reject) =>setTimeout(() => reject(new Error('Timeout')), timeout));return Promise.race([promise, timeoutPromise]);
}const fetchData = new Promise<string>((resolve) =>setTimeout(() => resolve('Fetched Data'), 2000)
);fetchWithTimeout(fetchData, 1000).then((data) => console.log(data)).catch((error) => console.error(error.message)); // 输出:Timeout