面试官:说一说try catch吧。。。。。。

面试官:说一说try catch吧
我:正好面试前看过,try catch只能捕获发生在当前执行上下文的错误,也就是同步执行代码块中的错误。
面试官:那说下这道题的执行结果

js 复制代码
try {
    new Promise(() => {
        throw new Error('error');
    })
    console.log(1111)
}catch {
    console.log('error');
}

我:会打印error,因为promise的函数参数是同步执行函数,抛出错误后会阻塞后边代码执行,所以1111不会打印,而catch会捕获到错误所以会打印error。
面试官:再下去了解了解吧,今天的面试先到这里。
我:。。。。。

面试结束后,我在编辑器中执行了一下这段代码,发现会打印1111,而且会抛出promise错误,catch并没有捕获到这个promise中抛出的错误。

我们都知道try catch是只可以捕获到同步代码块中的错误以及await错误的,而不能捕获到异步任务。

js 复制代码
// 同步错误
try {
    throw new Error('error');
    console.log(1111) // 不会打印
}catch {
    console.log('error') // 会打印error
}

// async await错误
const fn = async () => {
    return Promise.reject('error');
}

try {
    await fn();
    console.log(1111); // 不会打印
}catch {
    console.log('error') // 会打印error
}

// 异步,会直接抛出错误 不会捕获到
try {
    settimeout(() => {
        throw new Error('error');
    }, 0)
    console.log(1111) // 会执行
}catch {
    console.log('error'); // 不会打印
}

try {
    new Promise().then(() => {
        throw new Error('error');
    })
     console.log(1111) // 会执行
}catch {
    console.log('error'); // 不会打印
}

那为什么面试官写的那段代码明明是同步执行的为什么也不会捕获到呢?我们先来看一下promise。

我们都知道,一个 Promise 必然处于以下几种状态之一:

  • 待定(pending):初始状态,既没有被兑现,也没有被拒绝。
  • 已兑现(fulfilled):意味着操作成功完成。
  • 已拒绝(rejected):意味着操作失败。

当一个 Promise 被 reject 时,该 Promise 会变为 rejected 状态,控制权将移交至最近的 rejection 处理程序。最常见的 rejection 处理程序就是 catch handler或者 then 函数的第二个回调函数。而如果在 Promise 中抛出了一个错误。这个 Promise 会直接变成 rejected 状态,控制权移交至最近的 error 处理程序。

在我们 new 一个新的 Promise 时,这个 Executor 就会立即被塞入到当前的执行上下文栈中进行执行。但是,在 Executor 中 throw 出的错误,并不会被外层的 try...catch 捕获到。其原因是因为,在 Executor 函数执行的过程中,实际上有一个隐藏的机制,当同步抛出错误时,相当于执行了 reject 回调,让该 Promise 进入 rejected 状态。而错误也不会影响到外层的代码执行。

其实也就是说不管是promise的Executor同步抛出错误还是在then中异步抛出错误都只能通过特定的handler去进行捕获。这也就解释了为什么这段代码会这么执行了

js 复制代码
try { 
    new Promise(() => { throw new Error('error'); })  // 只能通过特定的handler进行捕获
    console.log(1111) // 不会影响后续代码的执行
}catch { 
    console.log('error'); // try catch不会捕获到
}
js 复制代码
try { 
    new Promise(() => { throw new Error('error'); }).catch(() => {
        console.log('catch error') // 会打印
    })  // 只能通过特定的handler进行捕获
    console.log(1111) // 后续代码还会执行
}catch { 
    console.log('error'); // try catch不会捕获到
}

那为什么使用async await之后又可以在try catch中捕获到promise的错误了呢?而且如果发生了错误,await后边的代码又不会执行了呢?

js 复制代码
const asyncErrorThrow = () => {
  return new Promise((resolve, reject) => {
    // 业务代码...
    throw new Error('抛出错误');
    // 业务代码...
  })
}
const testFun = async () => {
  try {
    await asyncErrorThrow();
    console.log("async 函数中的后续流程"); // 不会执行
  } catch (error) {
    console.log("若错误发生 async 函数中的后续流程"); // 会执行
  } 
}
testFun();

简单来说,await其实就是把异步代码来同步执行了,那同步执行的代码如果发生了错误,肯定可以被try catch捕获到,并且错误后边的代码也不会折行了。

可以看下黄玄大佬的解释:

MDN中的描述:

相关推荐
梦曦i13 小时前
@meng-xi/create-uni-app vs unibest:轻量脚手架与重型框架的定位之争
前端·uni-app
平头哥技术团队13 小时前
Day 10 | 工欲善其事:VS Code 配置与项目归档
android·开发语言·前端·javascript·html·交互
乌恩大侠14 小时前
GH200 新增 NVMe SSD 分区、格式化与挂载完整流程
运维·服务器·前端
yume_sibai14 小时前
Element Plus 数据展示组件完全指南(15个核心组件)
前端·javascript·vue.js
qiuhaipeng114 小时前
Claude code 升级后上下文长度变短问题
java·前端·数据库
zzz_236814 小时前
个人 AI 记忆如何跨工具复用:用 Markdown、索引和 Skill 搭一个可治理的记忆库
前端·人工智能·react.js·前端框架·agent·agent测评
剑之所向16 小时前
.NET 官方`System.Threading.Channels`
前端·javascript·数据库
计算机魔术师17 小时前
GPT-6 Astra幻觉砍到2%,却被一种老招数轻松绕过
前端
cjy00011117 小时前
2026AI 产品如何从一次性 Demo 变成可重复使用的业务工具?
前端·人工智能·fde
IT_陈寒17 小时前
React的状态更新坑得我差点加班到天亮
前端·人工智能·后端