跳到主要内容

TypeScript 异步工具函数

在现代JavaScript和TypeScript开发中,异步编程是不可或缺的一部分。无论是处理网络请求、文件读写,还是定时任务,异步操作都无处不在。为了简化异步编程,TypeScript提供了一些强大的工具函数,帮助我们更高效地处理异步任务。

本文将介绍一些常用的TypeScript异步工具函数,并通过实际案例展示它们的应用场景。

什么是异步工具函数?

异步工具函数是指那些专门用于处理异步操作的函数。它们可以帮助我们更好地管理异步任务,避免回调地狱(Callback Hell),并使代码更具可读性和可维护性。

常用的异步工具函数

1. Promise.all

Promise.all 是一个非常有用的工具函数,它允许我们并行执行多个异步任务,并在所有任务完成后返回结果。

typescript
const fetchUser = (userId: number): Promise<string> => {
return new Promise((resolve) => {
setTimeout(() => resolve(`User ${userId}`), 1000);
});
};

const fetchUsers = async (userIds: number[]): Promise<string[]> => {
const promises = userIds.map((id) => fetchUser(id));
return Promise.all(promises);
};

fetchUsers([1, 2, 3]).then((users) => console.log(users));
// 输出: ["User 1", "User 2", "User 3"]
提示

Promise.all 会等待所有的 Promise 都完成后才返回结果。如果其中一个 Promise 被拒绝(rejected),整个 Promise.all 也会被拒绝。

2. Promise.race

Promise.racePromise.all 类似,但它只返回最先完成的 Promise 的结果。

typescript
const fetchFastestUser = async (userIds: number[]): Promise<string> => {
const promises = userIds.map((id) => fetchUser(id));
return Promise.race(promises);
};

fetchFastestUser([1, 2, 3]).then((user) => console.log(user));
// 输出: "User 1"(假设第一个任务最先完成)
警告

Promise.race 只关心最先完成的 Promise,无论它是成功还是失败。因此,在使用时需要谨慎处理可能的错误。

3. Promise.allSettled

Promise.allSettledPromise.all 的一个变体,它会等待所有的 Promise 都完成(无论成功还是失败),并返回每个 Promise 的结果。

typescript
const fetchUsersWithErrors = async (userIds: number[]): Promise<PromiseSettledResult<string>[]> => {
const promises = userIds.map((id) => {
if (id === 2) {
return Promise.reject("User not found");
}
return fetchUser(id);
});
return Promise.allSettled(promises);
};

fetchUsersWithErrors([1, 2, 3]).then((results) => console.log(results));
// 输出: [
// { status: "fulfilled", value: "User 1" },
// { status: "rejected", reason: "User not found" },
// { status: "fulfilled", value: "User 3" }
// ]
备注

Promise.allSettled 非常适合处理那些可能部分成功、部分失败的异步任务。

4. async/await

async/await 是处理异步操作的另一种方式,它使得异步代码看起来更像同步代码,从而提高了代码的可读性。

typescript
const fetchUserData = async (userId: number): Promise<void> => {
try {
const user = await fetchUser(userId);
console.log(user);
} catch (error) {
console.error(error);
}
};

fetchUserData(1);
// 输出: "User 1"
提示

async/awaitPromise 的语法糖,它使得异步代码更易于理解和维护。

实际应用场景

场景1:并行请求

假设我们需要从多个API端点获取数据,并在所有数据都返回后进行进一步处理。这时,Promise.all 就派上了用场。

typescript
const fetchDataFromMultipleEndpoints = async (urls: string[]): Promise<any[]> => {
const promises = urls.map((url) => fetch(url).then((response) => response.json()));
return Promise.all(promises);
};

fetchDataFromMultipleEndpoints([
"https://api.example.com/users/1",
"https://api.example.com/users/2",
]).then((data) => console.log(data));

场景2:超时处理

在某些情况下,我们可能希望为异步操作设置一个超时时间。这时,Promise.race 可以帮助我们实现这一需求。

typescript
const fetchWithTimeout = (url: string, timeout: number): Promise<Response> => {
const fetchPromise = fetch(url);
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => reject(new Error("Request timed out")), timeout);
});
return Promise.race([fetchPromise, timeoutPromise]);
};

fetchWithTimeout("https://api.example.com/users/1", 5000)
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.error(error));

总结

TypeScript提供了多种异步工具函数,帮助我们更高效地处理异步任务。通过合理使用这些工具函数,我们可以避免回调地狱,提升代码的可读性和可维护性。

  • Promise.all:并行执行多个异步任务,等待所有任务完成。
  • Promise.race:返回最先完成的异步任务的结果。
  • Promise.allSettled:等待所有异步任务完成,无论成功还是失败。
  • async/await:使异步代码看起来像同步代码,提高可读性。

附加资源

练习

  1. 使用 Promise.all 并行获取多个API端点的数据,并在所有数据返回后进行处理。
  2. 使用 Promise.race 实现一个带有超时功能的异步请求。
  3. 使用 Promise.allSettled 处理一组可能部分成功、部分失败的异步任务。

通过练习,你将更好地掌握这些异步工具函数的使用方法。