全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-690-7320

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,但没有阻止后续代码的执行。

OneStory OneStory

OneStory 是一款创新的AI故事生成助手,用AI快速生成连续性、一致性的角色和故事。

OneStory 319 查看详情 OneStory

模拟 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运营策略  # 赤峰网站优化外包  # 白帽seo术语  # 石家庄网站排行优化  # 商洛网站推广哪家好  # 定制网站建设售后服务  # 营销策划推广税率是多少  # js  # 如何用  # 如何使用  # 至关重要  # 这是因为  # 可以使用  # 并将  # 抛出  # 设置为  # 执行器  # ai 


相关文章: 拼多多购物车商品数量无法修改如何处理 拼多多购物车操作优化方法  铁路12306卧铺选择攻略 铁路12306下铺座位预定技巧  我的世界官方游戏入口 我的世界官网平台直达链接  LINUX怎么设置定时任务_LINUX crontab配置教程  Python中高效且防溢出的双曲正弦计算:基于对数空间的优化策略  Golang如何实现微服务鉴权与权限控制_Golang微服务鉴权与权限管理实践  J*aScript动态修改指定div内所有a标签样式指南  CSS布局中意外空白:解决padding-top导致的顶部间距问题  Gmail邮箱申请注册直达_Gmail邮箱免费注册PC版官网入口2025  Yii2模块参数配置指南:正确声明与访问模块级配置  妖精漫画网页版登录入口免费_妖精漫画官网主页直接阅读漫画  C#使用XPath查询节点时出错? 常见语法错误与调试技巧  星露谷物语官网入口 星露谷物语游戏官网入口  邮政编码查询不到怎么办_邮政编码查询不到的常见原因与对策  树莓派传感器触发:通过Twilio API发送WhatsApp消息教程  AI泡沫首次被“刺破”:GPU十年都无法存活!  Win11怎么开启省电模式_Win11电池节电模式自动开启  qq游戏手机版下载安装_qq游戏移动端入口  PostgreSQL海量数据高效导入策略:Python与Django实践指南  css卡片内容溢出如何处理_使用overflow隐藏或scroll显示内容  mc.js免安装版 mc.js一键畅玩入口  c++中的std::forward_list和std::list有什么不同_c++ forward_list与list区别分析  C++如何连接MySQL数据库_C++使用Connector/C++操作MySQL数据库教程  AO3最新镜像入口 Archive of Our Own官方平台访问  J*a中实现Go语言select通道多路复用机制  PHP表单提交后函数重复执行的解决方案:管理$_POST数据  迅雷下载到U盘速度很慢怎么办_迅雷U盘下载慢优化方法  Golang如何优化CPU绑定任务分配策略_Golang CPU任务分配优化实践  PHP文件上传至S3:策略、考量与避免本地存储的挑战  12306选座怎么选到商务座_12306商务座选择与配置说明  优化LangChain文档加载与ChromaDB集成:解决多文档处理与分块问题  React/Next.js中实现列表项的动态选择与移动  PHP中获取MongoDB服务器运行时间(Uptime)的专业指南  Win11怎么安装Linux子系统 Win11 WSL2安装Ubuntu及环境配置指南  Go语言HTML解析:利用Goquery精准获取指定元素内容  快手极速版在线观看 官方网页版登录地址  Win10系统服务哪些可以禁用 Win10安全优化服务列表【干货】  FullCalendar 自定义按钮样式定制指南  Python模块化编程:有效管理依赖与避免循环引用  Composer的 "check-platform-reqs" 命令有什么用_在部署前检查生产环境是否满足Composer依赖需求  《噬血代码2》新预告片发布 展示游戏剧情  Yandex官方入口网址 Yandex俄罗斯搜索引擎最新在线地址  AO3官方在线访问地址 Archive of Our Own最新镜像合集  格力空气能E5故障代码是什么情况_格力空气能E5代码解析与应对措施  Go语言中对Map值调用带指针接收者方法:原理与最佳实践  Angular响应式表单:实现提交后表单及按钮的禁用与只读化  自定义Bag-of-Words实现:处理带负号的词汇权重  海量存储:机器视觉智能化的核心基石  狙击外星人小游戏开始_狙击外星人小游戏立即开始  HuggingFaceEmbeddings中向量嵌入维度调整的限制与理解 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。