try…catch…finally

使用 try 包住可能会发生错误的代码,如果 try 代码块中发生错误则执行 catch 块内的代码,不管怎么样,最终都会执行 finally 块内的代码

try {
  // code...
} catch (error) {
  // error...
} finally {
  // 最终处理程序
}

catch 如果用不到参数,可以直接省略括号ES2019

try {
  // ...
} catch {
  // ...
}

Tip

  • try 中有 return,catch 中有 throw,也会在跳出之前先执行 finally
  • 如果多个地方都有 return,函数的返回值取决于最后一个能执行到的 return

throw

抛出一个自定义的异常,可以根据内建错误类型创建自定义错误信息的 Error:throw new Error('message')

语法错误

如果代码中有语法错误,会在语法检查阶段报错,不会进入 try…catch 流程:

try {
  * // 语法错误
} catch (error) {
  console.log(error)
}

500

异步错误

try...catch 能捕捉到的异常,必须是主线程执行已经进入 try…catch,但 try…catch 尚未执行完的时候抛出来的

1. setTimeout 异步函数中的错误无法捕获

try {
  setTimeout(() => {
    console.log(x)
  }, 0)
} catch (error) {
  console.log(error)
}

500

2. promise 里面的错误也无法捕获

try {
  new Promise(() => {
    console.log(x)
  })
} catch (error) {
  console.log(error)
}

500

如果需要捕获 promise 里的异常,可以使用 async/await:

async function fn() {
  try {
    await new Promise(() => {
      console.log(x)
    })
  } catch (error) {
    console.log(error)
  }
}
 
fn()

300

promise 里的错误会优先被 promise.catch 捕获:

async function fn() {
  try {
    await new Promise(() => {
      throw new Error('promise error')
    }).catch(error => {
      console.log('promise.catch:', error)
    })
  } catch (error) {
    console.log('try...catch:', error)
  }
}
 
fn()

300

try-catch 能抛出 promise 的异常吗 - 掘金 (juejin.cn)
trycatch 不能捕获运行时异常_面试官:用一句话描述 JS 异常是否能被 try catch 捕获到 ?… - 掘金 (juejin.cn)

捕获全局错误

window.onerror

在浏览器中,window.onerror 可以捕获全局的宏任务错误

window.onerror = function(message, source, lineno, colno, error) {
  // 函数参数:
  // *  message:错误信息(字符串)
  // *  source:发生错误的脚本URL(字符串)
  // *  lineno:发生错误的行号(数字)
  // *  colno:发生错误的列号(数字)
  // *  error:Error(对象)
}

window.unhandledrejection

在浏览器中:window.unhandledrejection 可以捕获 Promise 中没有被捕获的错误(当微任务队列末尾没有错误处理程序时会执行)

window.addEventListener('unhandledrejection', function(event) {
  // 这个事件对象有两个特殊的属性:
  console.log(event.promise) // 生成该 error 的 promise
  console.log(event.reason) // error 信息
})