31 异步编程与Promise ⏳之错误处理
在上篇中,我们学习了 async/await
的基本概念和用法。本篇将专注于如何在使用 Promise
和 async/await
的过程中进行错误处理。异步编程的一个重要特性就是能够优雅地处理错误,这对构建健壮的应用程序至关重要。
Promise中的错误处理
在 Promise
的链式调用中,错误处理通常通过 .catch()
方法来实现。.catch()
方法可以捕获在 Promise
执行过程中出现的任何错误。
基本错误处理示例
function riskyOperation(): Promise<number> {
return new Promise((resolve, reject) => {
const success = Math.random() > 0.5; // 随机成功或失败
if (success) {
resolve(42);
} else {
reject(new Error("操作失败"));
}
});
}
riskyOperation()
.then(result => {
console.log(`操作成功,结果是: ${result}`);
})
.catch(error => {
console.error(`发生了错误: ${error.message}`);
});
在上面的示例中,riskyOperation
函数返回一个 Promise
,该 Promise
可能会失败。在 .catch()
方法中,我们捕获了错误并进行了处理。
链式调用中的错误处理
当我们有多个 Promise
需要顺序执行时,如果其中一个 Promise
失败,后续的 .then()
不会被执行,这时我们依然可以使用 .catch()
来处理错误。
function fetchData(): Promise<number> {
return new Promise((resolve, reject) => {
// 模拟网络请求
setTimeout(() => {
const success = Math.random() > 0.5;
if (success) {
resolve(100);
} else {
reject(new Error("数据请求失败"));
}
}, 1000);
});
}
fetchData()
.then(data => {
console.log(`获取的数据: ${data}`);
return data * 2; // 继续处理数据
})
.then(result => {
console.log(`处理后的结果: ${result}`);
})
.catch(error => {
console.error(`错误: ${error.message}`);
});
在上述示例中,我们使用 fetchData
函数模拟了一个数据请求。如果请求失败,错误会被捕获并处理,后续数据处理将会被跳过。
async/await中的错误处理
在使用 async/await
时,错误处理的方式更为直观和优雅。我们可以使用 try...catch
语句来处理异步操作中的错误。
基本错误处理示例
async function asyncRiskyOperation(): Promise<number> {
if (Math.random() > 0.5) {
return 42;
} else {
throw new Error("操作失败");
}
}
async function main() {
try {
const result = await asyncRiskyOperation();
console.log(`操作成功,结果是: ${result}`);
} catch (error) {
console.error(`发生了错误: ${error.message}`);
}
}
main();
在这个例子中,我们在 async
函数中使用 try...catch
来捕获可能出现的错误。这样做的好处是使代码更加清晰易读。
包装多个异步操作的错误处理
当我们在一个异步函数中执行多个 await
操作时,单独的 try...catch
可以让我们处理每个操作的错误。
async function fetchAndProcessData() {
try {
const data = await fetchData();
console.log(`获取的数据: ${data}`);
const processedData = await processData(data);
console.log(`处理后的结果: ${processedData}`);
} catch (error) {
console.error(`在处理数据时发生错误: ${error.message}`);
}
}
async function processData(input: number): Promise<number> {
if (Math.random() > 0.5) {
return input * 2;
} else {
throw new Error("处理数据失败");
}
}
fetchAndProcessData();
在这个例子中,fetchAndProcessData
函数中包含了对 fetchData
和 processData
的 await
调用。如果其中任何一个操作失败,错误都会被捕获并输出相应的错误信息。
具体场景中的错误处理
在实际开发中,错误处理显得尤为重要,尤其是在进行网络请求或文件读取等操作时。我们可以通过细化错误处理的方式来提高代码的健壮性。
经典网络请求的错误处理
async function fetchUserData(userId: string): Promise<User> {
try {
const response = await fetch(`https://api.example.com/users/${userId}`);
if (!response.ok) {
throw new Error(`网络响应失败: ${response.statusText}`);
}
const userData = await response.json();
return userData;
} catch (error) {
console.error(`获取用户数据失败: ${error.message}`);
throw error; // 重新抛出错误,以便上层调用处理
}
}
在这个示例中,我们对网络请求进行了详细的错误处理。如果网络响应失败,我们生成了一个详细的错误信息并抛出,使得调用这个函数的地方可以进一步处理错误。
小结
错误处理是异步编程中不可或缺的一部分。使用 Promise
时,我们可以用 .catch()
来捕获错误;在使用 async/await
时,try...catch
提供了更直观的方式来处理错误。确保我们能捕获并处理错误,可以让我们的代码更加健壮,也能提供更好的用户体验。
在下一篇中,我们将继续探讨如何并发处理多个 Promise
,这是一个非常实用的技能,特别是在处理多个异步请求时。