JS try catch 与 return 的陷阱

897 阅读1分钟

普通 try catch

如下代码输出是?

const foo = () => {
    try {
        console.log(1);
    } catch (error) {
        console.log(2);
    } finally {
        console.log(3);
    }
};
​
console.log('foo()', foo());

执行步骤:

  1. 定义函数 foo 变量
  2. 执行外层log
  3. 执行 foo 函数
  4. 走到 try 输出 1
  5. 由于try内的代码没有报错,所以不执行
  6. 走到 finally 输出 3
  7. 最后回到外层log,输出 undefined

所以输出是:

image.png

下面增加难度

try 里面 return

留意注释,标注了代码变更:

const foo = () => {
    try {
        console.log(1);
        return 4; // 新增代码
    } catch (error) {
        console.log(2);
    } finally {
        console.log(3);
    }
};
​
console.log('foo()', foo());

try 里面加了 return,那么 finally 的代码还会执行吗?会的。

image.png

输出如下:

image.png

即使 try 里面有 return,那么 finally 仍然会执行。

咦,那如果 finally 也有 return 呢?函数就能返回两个值了?

try 和 finally 都有 return

const foo = () => {
    try {
        console.log(1);
        return 4;
    } catch (error) {
        console.log(2);
    } finally {
        console.log(3);
        return 5; // 新增代码
    }
};
​
console.log('foo()', foo());

finally 的 return 会覆盖掉 try 的 return。

image.png

这代码怎么越来越奇怪了呀,确实,并不推荐 finally 里写 return,正常写法应该是你需要foo函数的返回值,那么代码正常的话,就应该是在 try 里 return,代码抛出异常的话,就应该在 catch 里 return,finally应该只做一些 try 和 catch 都做出的时,比如关闭 loading:

const foo = async () => {
    try {
        this.loading = true;
        const data = await fetch('xxx');
        return data.list;
    } catch (error) {
        return [];
    } finally {
        this.loading = false;
    }
};

这才是更合理的写法。

image.png