JavaScript 异常处理 try...catch...finally

try…catch…finally

捕获并处理异常。支持嵌套。

function test(){
    
    
    try {
    
    
        // throw true;
        throw 9527;
    	// throw '我是一个字符串';
        // throw new Error('一个异常'); 
    }
    catch (e) {
    
    
        if(typeof e === 'boolean'){
    
    
            console.error("catch 到 boolean:", e);
        }
        if(typeof e === 'number'){
    
    
            console.error("catch 到 number:", e);
        }
        if(typeof e === 'string'){
    
    
            console.error("catch 到 string:", e);
        }
        if (e instanceof Error) {
    
    
            console.error("catch 到:", e.message);
        }
    }
    finally {
    
    
        console.log("finally 块始终触发");
    }
}

throw

  1. throw 可以直接抛基础类型,也可以抛对象。
  2. 有需要的话可以自定义异常类型,默认JS也带了一些

异步中的异常问题

  1. 同步代码 try catch 无法捕获异步方法中抛出的异常。包括Promise.reject
try{
    
    
    Promise.reject('失败');
}catch(err){
    
    
    console.error(`try catch 捕获:${
      
      err}`);
}
// Promise {<rejected>: '失败'}
// Uncaught (in promise) 失败
try{
    
    
    Promise.resolve('成功').then(data => {
    
    throw new Error(`${
      
      data}个鸡儿!`);});
}catch(err){
    
    
    console.error(`try catch 捕获:${
      
      err}`);
}
// Promise {<rejected>: Error: 你成功个鸡儿!
// Uncaught (in promise) Error: 你成功个鸡儿!
  1. 异步的异常要用链式的.catch捕获。它是then(undefined, 拒绝(data)) 的简写。
try{
    
    
    Promise.reject('失败').catch(err=>console.log(`异步的.catch 捕获:${
      
      err}`));
}catch(err){
    
    
    console.error(`try catch 捕获:${
      
      err}`);
}
// 异步的.catch 捕获:失败
try{
    
    
    Promise.resolve('成功')
        .then(data => {
    
    throw new Error(`${
      
      data}个鸡儿!`);})
        .catch(err=>console.log(`异步的.catch 捕获:${
      
      err}`));
}catch(err){
    
    
    console.error(`try catch 捕获:${
      
      err}`);
}
// 异步的.catch 捕获:Error: 你成功个鸡儿!
  1. 可以使用 async...await 配合 Promise 转成同步执行,实现 try catch 捕获。但前提是没有被链式.catch截胡。
try{
    
    
    await Promise.reject('失败');
}catch(err){
    
    
    console.error(`try catch 捕获:${
      
      err}`);
}
// try catch 捕获:失败
try{
    
    
    await Promise.resolve('成功')
        .then(data => {
    
    throw new Error(`${
      
      data}个鸡儿!`);});
}catch(err){
    
    
    console.error(`try catch 捕获:${
      
      err}`);
}
// try catch 捕获:Error: 你成功个鸡儿!

下面这个就是被 .catch 截胡了。

try{
    
    
    await Promise.reject('失败').catch(err=>console.log(`异步的.catch 捕获:${
      
      err}`));
}catch(err){
    
    
    console.error(`try catch 捕获:${
      
      err}`);
}
// 异步的.catch 捕获:失败

当然 .catch 中也可以继续抛。这样外面 try catch 就又能捕获了。

try{
    
    
    await Promise.reject('失败')
        .catch(err=>{
    
    
            console.log(`异步的.catch 捕获:${
      
      err}`);
            throw '异步 .catch 继续抛的异常';
        });
}catch(err){
    
    
    console.error(`try catch 捕获:${
      
      err}`);
}
// 异步的.catch 捕获:失败
// try catch 捕获:异步 .catch 继续抛的异常

话说回来,如果再链一个 .catch 就又截胡了。。。

try{
    
    
    await Promise.reject('失败')
        .catch(err=>{
    
    
            console.log(`异步的.catch 捕获:${
      
      err}`);
            throw '异步 .catch 继续抛的异常';
        })
        .catch(err=>{
    
    
            console.log(`第二个异步.catch 截胡:${
      
      err}`);
        });
}catch(err){
    
    
    console.error(`try catch 捕获:${
      
      err}`);
}
// 异步的.catch 捕获:失败
// 第二个异步.catch 截胡:异步 .catch 继续抛的异常

函数嵌套调动时的 then、catch

  1. 多个函数嵌套调用形成的 Promise 链。
    可以成一个链看待,那么走 then 还是走 catch 的逻辑就清晰了。(脑补在调用子函数的位子把它包含的 then、catch 拼进来)
  2. 因为本质上是一条链,那么 catch 在前面的优先就高。后续是交给 catch 还是让下面的 then 继续,就看你的业务需要了。
function main() {
    
    
    return Promise.resolve('成功')
    .then(data => {
    
    
        console.log(`1、main 中的第一个 then:${
      
      data}`);	// 1 执行
        return subFun(data);
    })
    .then(data => {
    
    
        console.log(`4、main 中的第二个 then:${
      
      data}`);	// 4 执行
        return data;
    })
    .catch(err=>{
    
    										// 4.5 跳过
        console.log(`main 中的.catch 捕获到:${
      
      err}`)	// 此时状态 resolve 这个 catch 被跳过。
        return err;
    });
}

function subFun(data){
    
    
    return Promise.resolve('data')
        .then(data => {
    
    
            console.log(`2、subFun 中的第一个 then:${
      
      data}`);	// 2 执行
            throw `subFun 中抛异常`;								// 抛异常,从此走上 reject 之路
        })
        .then(data => {
    
    										// 2.5 跳过
            console.log(`subFun 中的第二个 then:${
      
      data}`);	// 此时状态 reject 这个 then 被跳过。
            return data;
        })
        .catch(err=>{
    
    
            console.log(`3、subFun 中的.catch 捕获:${
      
      err}`)	// 3 执行
            return err;										// 捕获异常,回归 resolve 之路
        });
}

main()
    .then(data => console.log(`5、最后的then:${
      
      data}`) )	// 5 执行
    .catch(err => console.error(`最后的catch :${
      
      err}`) );	// 5.5 跳过
1、main 中的第一个 then:成功
2、subFun 中的第一个 then:data
3、subFun 中的.catch 捕获:subFun 中抛异常
4、main 中的第二个 then:subFun 中抛异常
5、最后的then:subFun 中抛异常

参考资料

笑虾:JavaScript 学习笔记【Promise】结果处理(包含异常部分)

MDN:try…catch…finally
MDN:Error
MDN:throw

猜你喜欢

转载自blog.csdn.net/jx520/article/details/131124849