Promise 构造函数内部的异常为何没有阻止后续代码执行?


promise 构造函数内部的异常为何没有阻止后续代码执行?

Promise 构造函数内部的同步执行器(executor)中抛出的异常并不会立即中断整个脚本的执行。这是因为 Promise 内部机制会捕获这些异常,并将 Promise 的状态设置为 rejected,但不会阻止后续代码的执行。理解 Promise 的这种行为对于编写健壮的异步代码至关重要。

当我们在使用 new Promise() 创建 Promise 对象时,会传入一个执行器函数(executor)。这个执行器函数会被立即同步执行。如果在执行器函数内部发生了错误,例如调用了一个未定义的函数,我们可能会期望脚本立即停止执行。然而,实际情况并非如此。

Promise 内部的异常捕获机制

Promise 的设计初衷是为了更好地处理异步操作。为了保证异步操作的可靠性,Promise 内部实现了一个异常捕获机制。当执行器函数抛出异常时,Promise 会捕获这个异常,并将 Promise 的状态设置为 rejected。

具体来说,ECMAScript 规范中对 Promise 构造函数有如下定义:

Let completion be Completion(Call(executor, undefined, « resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]] »)).If completion is an abrupt completion, then a. Perform ? Call(resolvingFunctions.[[Reject]], undefined, « completion.[[Value]] »).Return promise.

第 10 步表明,如果执行器函数 (executor) 发生异常(abrupt completion),Promise 会调用 reject 函数,但不会阻止后续代码的执行,而是继续执行第 11 步,返回 Promise 对象。

示例代码与解释

考虑以下代码:

console.log('first');
const promise1 = new Promise((resolve, reject) => {
  console.log('inside executor');
  let what = 1;
  console.log(what()); // 抛出 TypeError
  console.log('not reached');
  resolve('Hi Guys!');
});
console.log('continues');

这段代码的输出如下:

first
inside executor
continues
Uncaught (in promise) TypeError: what is not a function
  at index.js:5:15
  at new Promise (<anonymous>)

可以看到,尽管 console.log(what()); 抛出了 TypeError,但 console.log('continues'); 仍然被执行了。这是因为 Promise 内部捕获了 TypeError,并将 promise1 的状态设置为 rejected,但没有阻止后续代码的执行。

度加剪辑 度加剪辑

度加剪辑(原度咔剪辑),百度旗下AI创作工具

度加剪辑 359 查看详情 度加剪辑

模拟 Promise 构造函数的内部实现

为了更好地理解 Promise 的行为,我们可以模拟 Promise 构造函数的内部实现:

class MyPromise {
  #state;
  #resolvedValue;
  #customers;

  constructor(executor) {
    this.#state = "pending";
    this.#customers = [];

    try {
      executor(
        (value) => this.#resolve(value),
        (reason) => this.#reject(reason)
      );
    } catch (err) {
      // 捕获异常,并允许执行继续
      this.#reject(err);
    }
  }

  #reject(reason) {
    if (this.#state !== "pending") return; // 忽略
    this.#state = "rejected";
    this.#resolvedValue = reason;
    this.#broadcast(); // 通知所有 then/catch 回调
  }

  #resolve(value) {
    if (this.#state !== "pending") return;
    this.#state = "fulfilled";
    this.#resolvedValue = value;
    this.#broadcast();
  }

  then(onFulfilled, onRejected) {
    return new MyPromise((resolve, reject) => {
      this.#customers.push({
        resolve: resolve,
        reject: reject,
        onFulfilled: onFulfilled,
        onRejected: onRejected,
      });

      if (this.#state === "fulfilled") {
        this.#broadcast();
      } else if (this.#state === "rejected") {
        this.#broadcast();
      }
    });
  }

  catch(onRejected) {
    return this.then(null, onRejected);
  }

  #broadcast() {
    if (this.#state === "fulfilled") {
      this.#customers.forEach((customer) => {
        if (customer.onFulfilled) {
          try {
            const result = customer.onFulfilled(this.#resolvedValue);
            customer.resolve(result);
          } catch (err) {
            customer.reject(err);
          }
        } else {
          customer.resolve(this.#resolvedValue);
        }
      });
    } else if (this.#state === "rejected") {
      this.#customers.forEach((customer) => {
        if (customer.onRejected) {
          try {
            const result = customer.onRejected(this.#resolvedValue);
            customer.resolve(result);
          } catch (err) {
            customer.reject(err);
          }
        } else {
          customer.reject(this.#resolvedValue);
        }
      });
    }
  }
}

// 使用示例
console.log("start");
const myPromise = new MyPromise((resolve, reject) => {
  console.log("inside executor");
  try {
    let what = 1;
    console.log(what());
    resolve("Success");
  } catch (error) {
    reject(error);
  }
});

myPromise
  .then((result) => {
    console.log("then:", result);
  })
  .catch((error) => {
    console.error("catch:", error);
  });

console.log("end");

在 MyPromise 类的构造函数中,try...catch 块捕获了执行器函数中可能抛出的异常,并通过 #reject 方法将 Promise 的状态设置为 rejected。

如何处理 Promise 中的异常

虽然 Promise 内部会捕获异常,但我们仍然需要显式地处理这些异常,以避免程序出现未知的错误。通常,我们可以使用 catch() 方法或 async/await 结合 try...catch 块来处理 Promise 中的异常。

  • 使用 catch() 方法:

    promise1
      .then((result) => {
        console.log('Result:', result);
      })
      .catch((error) => {
        console.error('Error:', error);
      });
  • 使用 async/await 结合 try...catch 块:

    async function myFunction() {
      try {
        const result = await promise1;
        console.log('Result:', result);
      } catch (error) {
        console.error('Error:', error);
      }
    }

总结

Promise 构造函数内部的异常不会立即中断整个脚本的执行,而是会被 Promise 内部机制捕获,并将 Promise 的状态设置为 rejected。为了保证程序的健壮性,我们需要显式地处理 Promise 中的异常,可以使用 catch() 方法或 async/await 结合 try...catch 块。理解 Promise 的这种行为对于编写可靠的异步代码至关重要。

以上就是Promise 构造函数内部的异常为何没有阻止后续代码执行?的详细内容,更多请关注其它相关文章!


# 高级编程  # 如何做优秀的营销号推广  # 重庆大型网站优化  # 水果网站建设素材  # SEO教程舞蹈幼儿简单  # 榆林网站推广招商电话  # 怎么知道快手关键词排名  # 营销推广方案模板百度  # 如何做好网站优化建设  # 河北公司推广营销  # 建筑机械推广哪个网站好  # js  # 如何实现  # 至关重要  # 这是因为  # 可以使用  # 鼠标  # 并将  # 抛出  # 设置为  # 执行器  # ai 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 优化推广96088 】 【 技术知识133117 】 【 IDC资讯59369 】 【 网络运营7196 】 【 IT资讯61894


相关推荐: 高德地图导航路线偏差报警频繁怎么办 高德地图路线偏差修复与优化方法  智慧职教mooc平台登录网址 智慧职教mooc官网直达  网页版网易云音乐入口_网易云音乐在线官网登录  抖音赚钱快速入门_新手必看的抖音赚钱步骤  《健康大兴》注册方法介绍  mysql如何配置从库只读_mysql从库只读设置方法  Go Goroutine调度与并发执行深度解析  驱动人生:游戏修复指南  Win11怎么录屏_Windows 11自带Xbox Game Bar录制视频  CodeIgniter 3 中基于 MySQL 数据高效生成动态图表教程  Python中对象引用与链表属性赋值的机制解析  百度小说看书时如何翻页_百度小说手动翻页与自动翻页设置  解决CSS布局中意外顶部空白问题的教程  realme 10 Pro息屏方案_realme 10 Pro省电策略  《红果免费短剧》下载观看方法  如何在CSS中设置背景图像:一个全面指南  mail.qq.com登录入口 QQ邮箱网页版直达  Go App Engine 项目结构与包管理深度指南  动漫之家观看全集库 动漫之家免费资源网地址  Lar*el 中高效执行多列更新:单次查询实现  苹果自助维修计划支持哪些设备机型  J*aScript实现网页表单实时输入字段比较与验证教程  Win11怎么设置分辨率 Win11显示设置调整分辨率及刷新率修改  sublime如何自定义文件类型图标_AFileIcon插件的主题切换与个性化配置  微博网页版入口链接 微博网页版在线互动平台  HTML中多图片上传与预览:解决ID冲突的专业指南  漫蛙官网(首页入口)_漫蛙漫画稳定访问教程分享  抖音号显示企业机构号是什么意思?企业机构号申请条件是什么?  J*aScript桌面应用_Electron多进程架构实战  《顺丰同城骑士》查看我的技能方法  猫眼app抢票快还是小程序快  苹果iPhone14ProMax如何新建AppleID_iPhone14ProMax新建AppleID具体流程  服装短视频如何起号推广?服装短视频起号推广有什么要求?  sublime怎么在文件中显示代码结构大纲_sublime符号列表功能  c++如何实现观察者设计模式_c++行为型设计模式实战  如何在 WordPress 前端实现内容提交:古腾堡编辑器的替代方案与实践  windows10怎么设置电源按钮_windows10按下电源键功能修改  《兴业银行》注册登录方法  Lar*el Eloquent中通过Join查询关联数据表:解决多行子查询问题  免费占卜在线神算_免费占卜手机神算  鼠标没反应了怎么办 无线/有线鼠标失灵的解决方法【详解】  《oppo商城》维修服务位置  C#解析并修改XML后保存 如何确保格式与编码的正确性  PHP odbc_fetch_array 返回值处理:如何正确访问嵌套数组元素  在XML中嵌入二进制数据(如图片)的最佳实践是什么? Base64编码与解析注意事项  《随手记》关闭首页消息推送方法  rabbitmq 持久化有什么缺点?  优化Asyncio嵌套函数调度:使用生产者-消费者模式实现并发流处理  j*a中赋值运算符是什么?  HTML与J*aScript实现下拉菜单驱动的动态表格:构建交互式维修表单 

 2025-11-02

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

运城市盐湖区信雨科技有限公司


运城市盐湖区信雨科技有限公司

运城市盐湖区信雨科技有限公司是一家深耕海外推广领域十年的专业服务商,作为谷歌推广与Facebook广告全球合作伙伴,聚焦外贸企业出海痛点,以数字化营销为核心,提供一站式海外营销解决方案。公司凭借十年行业沉淀与平台官方资源加持,打破传统外贸获客壁垒,助力企业高效开拓全球市场,成为中小企业出海的可靠合作伙伴。

 8156699

 13765294890

 8156699@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.