前提
通常我们在代码中捕获错误异常,使用的是try{ }catch{ }机制,今天在看项目时,突然发现里面使用try{ }finally{ }捕获异常,这种方法之前使用的还不是很多,所以也查了资料,深入研究研究。
try finally
(1)语法
异常机制中还有一个重要的部分,就是finally。
catch后面可以跟finally语句,语法如下所示:
try{
//可能抛出异常
}catch(Exception e){
//捕获异常
}finally{
//不管有无异常都执行
}
finally内的代码不管有无异常发生,都会执行。
(2)运行机制
- 如果
没有异常发生,在try内的代码执行结束后,就执行finally内代码 - 如果
有异常发生且被catch捕获,在catch内的代码执行结束后,就执行finally内代码 - 如果
有异常发生但没被捕获,则在异常被抛给上层之前执行
值得注意的是,try/catch/finally语法中,catch不是必需的,也就是可以只有try/finally,表示不捕获异常,异常自动向上传递,但finally中的代码在异常发生后也执行。
(3)return
(1)try中有return
在try / catch / finally 语句里面,有一个细节,就是如果在try或者catch内有return,则这时return语句会在finally语句执行结束后才会执行,但是finally并不能立即改变返回值,我们可以看下面代码:
import React , { useState , useEffect} from 'react';
const App = () => {
const [val , setVal] = useState(0)
const getResult = () => {
try {
return setVal(1234)
} catch (error) {
console.log('error',error)
}finally{
setVal(9999)
}
}
useEffect(() => {
getResult()
}, [])
return (
<div>
<h1>
哈哈啊哈哈哈
</h1>
<h2>
当前的val值:{val}
</h2>
</div>
);
};
export default App;
效果图:

可以看出:
这个函数的返回值是9999,而不是1234。实际执行过程是:
- 在执行到try内的
return setVal(1234)语句前时,会先将返回值val保存在一个临时变量中 - 然后才
执行finally语句 - 最后
try再返回那个临时变量,finally中对val的修改不会被返回
(2)finally中有return
如果在finally中也有return语句呢,这时会是什么情景呢?
如果finally里面也含有return,那么try和catch内的return会丢失,实际会返回finally中的返回值。
事实上,finally中有return不仅会覆盖try和catch内的返回值,还会掩盖try和catch内的异常,就像异常没有发生一样,比如说:
import React , { useState , useEffect} from 'react';
const App = () => {
const [val , setVal] = useState(0)
const getResult = () => {
try {
let aaa = 111/0
return setVal(aaa)
} catch (error) {
console.log('error',error)
}finally{
setVal(9999)
}
}
useEffect(() => {
getResult()
}, [])
return (
<div>
<h1>
哈哈啊哈哈哈
</h1>
<h2>
当前的val值:{val}
</h2>
</div>
);
};
export default App;
效果图:

可以发现:
- try里面的函数有错误,但是并没有异常抛出。
- finally里面的return把错误给覆盖掉了,而且不再向上传递。
其实,finally中不仅return语句会掩盖异常,如果finally中抛出了异常,则原异常就会被掩盖,看下面代码:
import React , { useState , useEffect} from 'react';
const App = () => {
const [val , setVal] = useState(0)
const getResult = () => {
try {
let aaa = 111/0
return setVal(aaa)
} catch (error) {
console.log('error',error)
}finally{
let bbb = 33/0
// throw new Error('出错了')
return (
setVal(bbb),
console.log('finally error')
)
}
}
useEffect(() => {
getResult()
}, [])
return (
<div>
<h1>
哈哈啊哈哈哈
</h1>
<h2>
当前的val值:{val}
</h2>
</div>
);
};
export default App;
效果图:

可以发现:
- finally里面抛出了错误
所以,一般而言,为避免混淆,应该避免在finally中使用return语句或者抛出异常,如果调用的其他代码可能抛出异常,则应该捕获异常并进行处理。
本文详细探讨了JavaScript中的try...finally语句块,解释了其运行机制。无论是否出现异常,finally块中的代码总会执行。当try或catch中有return时,finally会先执行,然后才返回try或catch的值。如果finally中包含return,它将覆盖之前的返回值,同时会隐藏异常,使得异常不会向上层传播。因此,避免在finally中使用return语句以防止混淆。
2714

被折叠的 条评论
为什么被折叠?



