在JavaScript中,我们需要对程序运行时的错误进行捕获和处理,确保程序不会因为未处理的错误而中断。同时,我们还需要根据同步或者异步以不同的方式处理异常。
同步异常
同步异常处理是通过try...catch语句完成的,如:
function sum(a, b) {
if (!+a || !+b) {
throw Error('args must be a numeric value');
}
return a + b;
}
try {
sum(1, 'A');
} catch (err) {
console.error(`Caught error: ${err.message}`);
}
异步异常
异步异常处理,则需要以不同的方式处理
Promise异常
使用Promise对象自身的.catch方法来捕获异常,如:
fetch('https://')
.catch((err) => console.error(`Caught error: ${err.message}`))
函数中异步调用异常
结合使用async/await和try...catch来捕获异常,如:
async function loadData() {
try {
const data = await fetch('https://')
.then((response) => response.data());
console.log(data);
} catch (err) {
console.error(`Caught error: ${err.message}`)
}
}
总结
- 使用
try...catch捕获同步异常 - 使用
.catch捕获Promise异常 - 自定义错误类型,提供更清晰的错误上下文,便于在
try...catch语句中对错误进行统一处理
下面是在实际开发中进行异常处理的例子:
// 自定义错误类型
class InvalidArgsError extends Error {
constructor(message, code = 100) {
super(message);
this.name = 'InvalidArgsError';
this.code = code;
}
}
class InternalError extends Error {
constructor(message) {
super(message);
this.name = 'InternalError';
}
}
async function readUserInfoFromDB(userId) {
return {
id: userId,
name: 'aric',
}
}
async function readUserInfoFromCache(userId) {
return null;
}
async function writeUserInfoToCache(userId, userInfo, expireTime) {
return true;
}
// 处理请求函数
async function getUserInfo(ctx, next) {
try {
const { userId } = ctx.request.query;
if (!userId || typeof userId !== 'string') {
throw new InvalidArgsError('"userId" must to be a non-empty string');
}
let userInfo = await readUserInfoFromCache(userId);
if (userInfo) {
return userInfo;
}
userInfo = await readUserInfoFromDB(userId);
// 采用异步调用形式,这样不会阻塞函数
writeUserInfoToCache(userId, userInfo, 5 * 60)
.catch((err) => console.error(`Write cache error: ${err.message}`));
ctx.body = {
userInfo,
};
} catch(err) {
console.error(`Caught error: ${err.message}`);
// 根据不同的错误类型进行特殊处理
if (err instanceof InvalidArgsError) {
ctx.status = 400;
ctx.body = {
message: err.message,
code: err.code,
};
} else {
ctx.status = 500;
ctx.body = {
message: 'Server is busy, please try again later',
};
}
}
}