写代码的时候,谁还没碰上过ref="/tag/46/" style="color:#E3A3CF;font-weight:bold;">程序突然崩溃的情况?比如读个文件,文件没了,程序直接卡死;或者网络请求超时,整个界面就僵在那里。其实这些问题,用好 throw 和异常捕获机制,完全可以优雅地处理。
什么是 throw?
throw 就是主动抛出一个异常。比如你写了个函数,要求传入的参数必须是正数,结果用户传了个负数进来,这时候你不该默默执行,而是应该“喊一声”——这个输入不对!
function calculateArea(radius) {
if (radius <= 0) {
throw new Error('半径必须大于0');
}
return Math.PI * radius * radius;
}
一旦执行到 throw,函数立刻停止,错误会被向上抛出,直到有人处理它。就像快递寄丢了,系统得告诉你“这单出问题了”,而不是假装一切正常。
try-catch 捕获异常
有抛出就得有接收。这时候就要靠 try-catch 来接住这些“意外”。比如你去加载一个配置文件,但不确定它是否存在。
try {
const config = JSON.parse(fs.readFileSync('config.json', 'utf8'));
console.log('配置加载成功', config);
} catch (error) {
console.warn('配置加载失败,使用默认设置');
const config = { timeout: 5000, retry: 3 };
}
这样即使文件读取失败,程序也不会崩,而是自动切换到默认配置,用户体验自然就好多了。
别乱 throw,也别啥都 catch
有些新手一看异常能处理,就开始滥用 catch,把所有错误都吞掉,最后程序出了问题却找不到日志。这就像家里漏水,你不修水管,反而天天拿拖把擦地。
同样,不该 throw 的时候乱 throw 也不行。比如一个判断用户名是否合法的函数,发现不合法就 throw,那每次校验都要包一层 try,调用方会很累。这种情况下,返回 false 更合适。
实际场景:表单提交防翻车
想象你在做一个注册页面,用户填完信息点提交。这时候你要检查邮箱格式、密码长度、是否勾选协议。如果哪一项不对,直接 throw 错误,然后在最外层用 try-catch 统一处理。
function validateForm(email, password, agreed) {
if (!email.includes('@')) {
throw new Error('请输入正确的邮箱');
}
if (password.length < 6) {
throw new Error('密码不能少于6位');
}
if (!agreed) {
throw new Error('请同意用户协议');
}
}
// 调用时
try {
validateForm(userEmail, userPwd, hasAgreed);
submitToServer();
} catch (error) {
alert(error.message);
}
这样逻辑清晰,出错也能准确定位,不会让用户点了提交没反应,也不知道哪儿错了。
finally 的妙用
有时候你希望不管有没有异常,某些代码都得执行。比如打开数据库连接后,无论操作成功还是失败,都得关闭连接。这时候 finally 就派上用场了。
let db = null;
try {
db = openDatabase();
db.query('UPDATE users SET last_login = NOW()');
} catch (error) {
console.error('更新失败', error);
} finally {
if (db) {
db.close();
}
}
就像做饭,不管你最后菜炒没炒成,火一定要关。