告别漫无目的try-catch

242 阅读3分钟

前言

在开发中try...catch常常被使用,主要用于捕获和处理同步代码中可能发生的异常 ,从而避免程序崩溃。并且让我们可以对异常进行处理。try-catch 应该用于处理程序中无法事先预见的异常情况,而不应该用于处理可以通过逻辑判断避免的问题。

大部分人对它的理解就是用来避免错误,防止程序报错。不管是什么情况下我先使用try...catch

正文

先来演示一下在使用try...catch时,不适当的使用。

几种错误

  1. 用异常来控制流程

网络上有一道面试题,如何跳出forEach循环,使用的就是try...catch。 这就是为了做题而写try...catch,也是典型的滥用,虽然这题目的是考你基础。

你不能使用forbreak

try {
  let nums = [1, 2, 3]

  nums.forEach((item) => {
    console.log(item);

    if (item == 2) {
      throw new Error('error')
    }
  })

} catch (e) {
  console.log(e)
}
  1. 可以通过逻辑判断避免异常,就是要使用try...catch

我们常通过接口来获取数据,但是有时候数据并不是我们理想的结构

try {
  //接口来的的
  let studentList = null;
  student.forEach(() => {
    console.log('student');
  })
} catch {
  console.log('error')
}

可以改为

let studentList = null;
studentList?.forEach(() => {
  console.log('student');
})

//----------------------------------------
let studentList = null;
if (studentList) {
  studentList.forEach(() => {
    console.log('student');
  })
}
  1. 使用异常进行状态检查

try...catch是用来捕获和处理代码执行过程中可能抛出的错误,而不是对某种情况进行检查

try {
  let info={
    name: 'zhangsan',
  }
  //表单的检查
  if(!info.age){
    throw new Error('age is required')
  }
} catch (e) {
  //提示用户错误
}

改为

let info = { name: 'zhangsan', }; 
// 表单的检查 
if (!info.age) 
{ 
    // 提示用户错误 
    console.error('Age is required'); 
    // 或者通过 UI 提示用户 
    alert('Age is required'); 
}

常见的使用场景

  1. 基本使用
let jsonString = '{"name": "John", "age": 30';

try {
  let obj = JSON.parse(jsonString);
} catch (e) {
  console.error("Parsing error:", e.message);
}
  1. 搭配async/await和异步方法使用
let step1 = () => {
  return new Promise((resolve, reject) => {
    console.log('step1');
    reject('step1 error')
  })
}

async function run() {
  try {
    let result1 = await step1()
  } catch (e) {
    console.log(e);
  }
}

run()

如果只有一件事要做,直接使用thencatch更好。

step1().then((res) => {

}).catch((err) => {

})

try...catch比较适合处理多件事。

let step1 = () => {
  return new Promise((resolve, reject) => {
    console.log('step1');
    resolve('step1')
  })
}

let step3 = () => {
  return new Promise((resolve, reject) => {
    console.log('step3');
    reject('step3 error')
  })
}


let step4 = () => {
  return new Promise((resolve, reject) => {
    console.log('step4');
    resolve('step4')
  })
}

async function run() {
  try {
    let result1 = await step1()
    let result3 = await step3()
    let result4 = await step4()
  } catch (e) {
    console.log(e);
  }
}

run()
  1. try...catch的嵌套

try...catch在嵌套使用的情况下,对异常的捕获遵循就近原则,看个例子。主程序会在步骤3捕获到异常,如果将注释的代码解开,哪个主程序会在步骤2捕获到异常。


let step1 = () => {
  return new Promise((resolve, reject) => {
    console.log('step1');
    resolve('step1')
  })
}

async function step2() {
  try {
    console.log('step2');
    await Promise.resolve('step2-1')
    await Promise.resolve('step2-2')
    await Promise.resolve('step2-3')
    await Promise.reject('step2-4')
  } catch (e) {
    console.log(e,'e');
    // throw new Error('step2 error')
  }
}

let step3 = () => {
  return new Promise((resolve, reject) => {
    console.log('step3');
    reject('step3 error')
  })
}


let step4 = () => {
  return new Promise((resolve, reject) => {
    console.log('step4');
    resolve('step4')
  })
}

async function run() {
  try {
    let result1 = await step1()
    let result2 = await step2()
    let result3 = await step3()
    let result4 = await step4()
  } catch (e) {
    console.log(e);
  }
}

run()

结语

感兴趣的可以去试试