扩展 Javascript Promise 并在构造函数内解析或拒绝它

2024-03-02

我想用 ES6 语法扩展原生 Javascript Promise 类,并且能够在子类构造函数中调用一些异步函数。根据异步函数结果,承诺必须被拒绝或解决。

然而,当then函数被称为:

  1. 子类构造函数执行两次
  2. 抛出“未捕获的类型错误:Promise 解析或拒绝函数不可调用”错误
    class MyPromise extends Promise {
        constructor(name) {
            super((resolve, reject) => {
                setTimeout(() => {
                    resolve(1)
                }, 1000)
            })

            this.name = name
        }
    }

    new MyPromise('p1')
        .then(result => {
            console.log('resolved, result: ', result)
        })
        .catch(err => {
            console.error('err: ', err)
        })

推理很简单,但不一定是不言而喻的。

  • .then()返回一个承诺
  • if then在 Promise 的子类上调用,返回的 Promise 是子类的实例,而不是 Promise 本身。
  • the then返回的 Promise 是通过调用子类构造函数来构造的,并向其传递一个内部执行器函数,该函数记录了resolve and reject传递给它的参数供以后使用。
  • “稍后使用”涵盖解决或拒绝返回的承诺then异步监视执行时onfulfilled or onrejected处理程序(稍后)以查看它们是否返回一个值(这解决了then返回的承诺)或抛出错误(拒绝承诺)。

简而言之then内部调用获取并记录对resolve and reject他们返回的承诺的功能。


So regarding the question,
new MyPromise( 'p1')

工作正常,并且是对子类构造函数的第一次调用。

.then( someFunction)

records someFunction在列表中then拨打的电话new MyPromise(记起then可以多次调用)并尝试通过调用创建返回承诺

new MyPromise( (resolve, reject) => ... /* store resolve reject references */

这是对子类构造函数的第二次调用then代码。构造函数预计(并且确实)同步返回。

在创建返回承诺后返回时,.then方法进行完整性检查以查看是否resolve and reject后面需要用到的函数其实就是函数。它们应该与提供的回调一起存储(在列表中)then call.

如果是MyPromise他们不是。执行者路过then, to MyPromise,甚至没有被调用。所以then方法代码抛出类型错误“Promise解析或拒绝函数不可调用” - 它无法解析或拒绝它应该返回的promise。

创建 Promise 的子类时,子类构造函数必须以执行器函数作为第一个参数,并用 real 调用执行器resolve and reject函数参数。这是内部要求的then方法代码。

做一些复杂的事情MyPromise,也许检查第一个参数以查看它是否是一个函数,如果是,则将其作为执行器调用,可能是可行的,但超出了本答案的范围!对于所示的代码,编写工厂/库函数可能更简单:

function namedDelay(name, delay=1000, value=1) {
     var promise = new Promise( (resolve,reject) => {
         setTimeout(() => {
                resolve(value)
            }, delay)
         }
     );
    promise.name = name;
    return promise;
}

namedDelay( 'p1')
    .then(result => {
        console.log('fulfilled, result: ', result)
    })
    .catch(err => {
        console.error('err: ', err)
    })

;TLDR

Promise 的类扩展不是扩展。如果是的话,则需要实现 Promise 接口并采用执行器函数作为第一个参数。您可以使用工厂函数返回异步解析的 Promise(如上所述),或者hack发布的代码与

MyPromise.prototype.constructor = Promise

什么导致.then返回一个常规的 Promise 对象。黑客本身驳斥了正在发生类扩展的想法。


Promise 扩展示例

以下示例显示了一个基本的 Promise 扩展,它添加了提供给构造函数的属性。值得注意的是:

  • The Symbol.toString getter https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toStringTag#custom_tag_with_tostringtag只影响将实例转换为字符串的输出。记录实例时,它不会将“Promise”更改为“MyPromise”object在经过测试的浏览器控制台上。

  • Firefox 89 (Proton) 不报告扩展实例自己的属性,而 Chrome 则报告 - 下面的测试代码按名称记录实例属性的原因。

class MyPromise extends Promise {
    constructor(exec, props) {
        if( typeof exec != "function") {
            throw TypeError( "new MyPromise(executor, props): an executor function is required");
        }
        super((resolve, reject) => exec(resolve,reject));
        if( props) {
            Object.assign( this, props);
        } 
    }
    get [Symbol.toStringTag]() {
        return 'MyPromise';
    }
}

// Test the extension:
const p1 = new MyPromise( (resolve, reject) =>
    resolve(42),
    {id: "p1", bark: ()=>console.log("woof") });

console.log( "p1 is a %s object", p1.constructor.name);
console.log( "p1.toString() = %s", p1.toString());
console.log( "p1.id = '%s'", p1.id);
console.log( "p1 says:"); p1.bark();

const pThen = p1.then(data=>data);
console.log( "p1.then() returns a %s object", pThen.constructor.name);
let pAll = MyPromise.all([Promise.resolve(39)]);
console.log( "MyPromise.all returns a %s object", pAll.constructor.name);
try { new MyPromise(); }
catch(err) {
    console.log( "new MyPromise() threw: '%s'", err.message);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

扩展 Javascript Promise 并在构造函数内解析或拒绝它 的相关文章

  • Nodemon - 使用配置文件指定扩展监视列表

    有没有办法使用配置文件而不是命令行来指定监视列表 Nodemon 文档中的命令行方法 我尝试使用nodemon json配置文件包含以下内容 ext js json hbs html 返回 扩展名匹配 错误 然后我尝试将配置添加到packa
  • 调整表格上的列宽

    目前 如果表格的宽度不大于容器的宽度 我可以调整表格列的大小 我希望发生的是在调整列大小时表格的宽度增加 以便滚动条出现在表格下方 基本上允许我调整大小而不受容器宽度的限制 这是一个小提琴 https jsfiddle net thatOn
  • 使用Web蓝牙API时找不到移动设备

    我正在学习 Web 蓝牙 API 使用 google 开发控制台 我无法找到我的移动设备 还尝试了 github 上提供的演示 https github com WebBluetoothCG demos https github com W
  • 现在 JavaScript 的无限循环会导致浏览器崩溃吗?

    我正在学习 JavaScript 对编程很陌生 碰巧遇到了这些无限循环 据说这些循环会永远持续下去并使浏览器崩溃 但是当我用这些代码创建一个循环时 i 0 while i lt 10 document write i 浏览器只是继续加载它
  • 如何在前端和后端之间共享javascript代码(ES6)

    这是 ES6 特定的副本这个所以线程 https stackoverflow com questions 3225251 how can i share code between node js and the browser 其中详细介绍
  • 如何字符串化整个 Javascript 对象(包括 __proto__ 属性)?

    如果这是重复的 我很抱歉 到目前为止我找不到相同的问题 我的对象中有一个具有各种方法的对象 proto 成员 我们称这个对象的类型为myObjectType 稍后我必须做一个JSON stringify myObjectType 问题是 当
  • 如何使用canvas获取html5中的视频截图

    您好 是否可以使用 html 5 canvas 捕获正在播放的视频的屏幕截图 看起来这里是可能的 http html5doctor com video canvas magic http html5doctor com video canv
  • JavaScript 中最大长度的正则表达式

    如何限制与正则表达式匹配的字符串的长度 我假设var sixCharsRegEx 6 7 只匹配长度为 6 或 7 的字符串 but no http jsfiddle net FEXbB http jsfiddle net FEXbB 我缺
  • 如何在 React JS 组件中预加载图像?

    我目前正在渲染一个子组件signInError发生 这signInError存储在父组件中 如果不为 null 则渲染
  • 创建地图后向 Google 地图 v3 添加标记

    我对使用 Google Maps API 比较陌生 现在我正在开发一个项目 用户可以选择各种搜索过滤器并查看结果自动显示在地图上 而无需重新加载页面 到目前为止 我的方法是创建一个控制地图的 Javascript 对象 以便我可以按照我的意
  • 通过 JavaScript 获取页面/iframe 的编码

    我想通过 JavaScript 或浏览器中的其他一些 API 以编程方式确定页面的编码 我想要这些信息的原因是因为我试图对主要浏览器支持的字符编码进行模糊测试 显然仅仅因为我发送了适当的 内容类型 并不意味着浏览器会使用编码做正确的事情 欢
  • 检查 IE8 是否使用纯 Javascript [重复]

    这个问题在这里已经有答案了 我以前是这样检查的 browser msie browser version 8 但似乎 browser已从 jQuery 的更高版本中删除 So 我怎样才能用纯javascript检查这一点 I tried i
  • 在 d3v4 堆积条形图中使用 JSON

    我找到了一个d3v3堆积条形图示例 http bl ocks org mstanaland 6100713我想使用它 因为它使用 json 数据 还有一个d3v4规范条形图示例 https bl ocks org mbostock 3886
  • 更改 jQuery 中链接的标题

    我有一个 id 为 helpTopicAnchorId 的链接 我想在 jQuery 中更改其文本 我该怎么做呢 helpTopicAnchorId text newText P S the jQuery 文档 http docs jque
  • Chrome 开发工具中 $() 和 $(this) 显示的 x.fn.x.init[] 值是多少

    我有在一些开发工具中调试 JS 和 jQuery 脚本的习惯 我意识到 Chrome 开发工具将 x fn x init 显示为 和 this 的值 但是我不知道这些价值是什么 Code
  • 来自 geoJSON 的 Google 地图航点

    我想从 geoJSON 文件加载行程 目前来说 它是有效的 但只有两点 但我需要添加 4 或 5 个航路点 我的代码只读取前两个点并将它们设置为起点和目的地 这是我的代码 google maps event addListener map
  • 过早退出 Qualtrics 中的循环和合并块

    我目前正在进行一项 Qualtrics 调查 受访者必须解决一长串字谜问题 然后回答一些人口统计问题 为了使变位词部分更容易 我使用了循环和合并块 第一个字段是要解决的变位词 第二个字段是变位词的解决方案 因此调查可以根据受访者的答案来检查
  • 用圆形雷达数学方法表示点

    我正在编写一个简单的应用程序 它可以向您显示您周围的朋友 但不是在法线地图中 而是在像 UI 这样的真正圆形雷达上 https i stack imgur com Au3IP png https i stack imgur com Au3I
  • .js.erb VS .js

    将 Rails 应用程序的 javascript 放入 js erb 文件而不只是将其放入 application js 文件有什么好处 我有一个企业创建按钮 因此我应该将代码放入 create js erb 文件中 还是使用以下方法将其放
  • 使用node.js/Express从HTTP重定向到HTTPS

    有什么方法可以更改我的 Web 应用程序以侦听 HTTPS 而不是 HTTP 我正在使用node js express 我需要它来侦听 HTTPS 因为我正在使用地理定位 而 Chrome 不再支持地理定位 除非从 HTTPS 等安全上下文

随机推荐

  • 使用for循环遍历java中的列表

    如何使用索引迭代列表数据结构 例如 考虑一个列表形式的句子 每个元素都是一个单词 我可以使用索引逐步浏览每个单词吗 像这样的事情 sentence defined something like this List
  • Django、ModelChoiceField() 和初始值

    我正在使用这样的东西 field1 forms ModelChoiceField queryset 如何使我的表单显示所选的值 如果你想设置默认的初始值 你应该定义initial http docs djangoproject com en
  • 如何将字体精美的图标放入选择下拉菜单中?

    我一直在努力在 vuejs 的选择下拉菜单中设置一个很棒的字体图标 我尝试过一些方法 比如
  • 在javascript中使用map或reduce将二维数组转换为对象

    是否可以转换 35 Bill 20 Nancy 27 Joan to Bill 35 Nancy 20 Joan 27 使用 map or reduce 方法 我可以使用以下方法转换数组 const arr 35 Bill 20 Nancy
  • Corona SDK 的本地通知 (Android)

    有没有办法在使用 Corona SDK 时实现本地通知 这是 Android 特定的 因为我们已经找到了 iOS 方向 Cheers 目前 Corona 上的本地通知仅适用于 iOS Android 版本尚未完成 完成后 我将按照 Andr
  • 将 Numpy 矩阵显示为视频

    我有一个 numpy 矩阵 其中每一行都是一张图片 我可以重塑行并使用 matplotlib pyplot 显示图像 问题是 我不想单独显示图像 我想像视频一样依次显示它们 这在Python中怎么可能呢 好吧 我不知道这是否是最好的方法 但
  • 包含(大多数)所有元素的 HTML 页面,用于样式设置

    是否有人拥有或知道包含所有元素 带有口语文本或其他内容 的 HTML 页面 我可以做一个 但我想一定有人已经这样做了 当开始一个项目时 我喜欢为链接 列表 表格等设置一些基本样式 包含所有元素的 HTML 页面将帮助我加快此过程 我很乐意创
  • 如何在 iOS 6 中启动具有特定地址的 iOS 地图应用程序?

    我有一个应用程序 允许用户启动地图应用程序 Google 或 Apple 来查看地址 我曾经这样做过 Address address self person addresses objectAtIndex 0 NSString addres
  • 访问页面时自动点击页面上的锚链接

    我之前问过这个问题 但一些专家告诉我补充一下 这可以重新加载给定的链接 但我想知道如何在 id 的帮助下单击元素 锚点 是否有任何代码在执行时会单击 id dp99 并且我希望在访问页面时执行此 javascript 这是 HTML a h
  • Cordova、iOS 和 iframe 不会加载内容,除非我允许访问 href="*"

    我有一个网络应用程序 它有一个嵌入式地图字段 它是使用 iframe 实现的https maps google com https maps google com 我正在将我们的应用程序 当前作为主屏幕图标运行 移植到 iOS 上的 Cor
  • 在 C++ 中将数据从一个线程发送到另一个线程的最快方法是什么?

    我尝试过构建一个简单的生产者 消费者程序的实验 它们在单独的线程中运行 生产者生成一些数据 消费者在另一个线程中获取它 我实现的消息传递延迟约为 100 纳秒 谁能告诉我这是否合理或者是否有更快的实现 我没有使用锁 只是简单的内存计数器 我
  • OpenGL 中的动画 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我想请您分享一些关于如何在 OpenGL 应用程序中实现动画支持的想法 例如 如果我们希望在用户输入触发某些事件的情况下 在屏幕上为球
  • 增加 Kafka 消费者在单次轮询中读取的消息数量

    Kafka消费者有一个配置max poll records它控制单次调用 poll 及其返回的最大记录数默认值为 500 https kafka apache org documentation max poll records 我已将其设
  • 如何判断一个点(X,Y)是否包含在圆的弧段内(即饼图切片)?

    想象一个圆圈 想象一下一个馅饼 想象一下 尝试返回一个布尔值 该布尔值确定所提供的 X Y 参数是否包含在这些饼图块之一中 我对弧线的了解 我有 CenterX CenterY 半径 StartingAngle EndingAngle St
  • 如何加快 AWS 设备场上的 Selenium 测试速度?

    我正在使用 Python 在 AWS 设备场上进行测试 看来开始使用硒需要非常非常长的时间 这是我使用的代码 from time import time from boto3 import client from selenium impo
  • 增加 sas 内存/memsize

    您好 有一个包含大约 6000 个观测值和 250 个变量的数据集 我正在尝试使用 proc mix 在 sas 中运行混合模型 但我不断收到 错误 由于内存不足 sas 系统停止处理此步骤 我尝试了康奈尔大学的方法 http www ci
  • 为什么@RequestBody得到一个带有null属性的对象

    我有一个 springboot REST 控制器 其中包含所示的 PATCH 和 PUT 请求方法 由于某种原因 RequestBody 公司 的字段 属性作为空值出现 我缺少什么 我在前端使用 angular8 它正在执行 PATCH 调
  • 在移动网站上禁用 JavaScript

    我的网站上有一个聊天小部件 它占据了手机的整个屏幕 如何在一定宽度的设备 或手机 上禁用聊天设备
  • “可视化页面编辑器对 Windows 64 位提供实验性支持”

    我正在使用 Eclipse Luna 和 JBoss AS 7 当我在 Eclipse 中创建 JSP 页面时 出现以下错误 我将服务器更改为 Tomcat 7 但仍然遇到相同的错误 这是如何引起的以及如何解决 该可视化页面编辑器是JBos
  • 扩展 Javascript Promise 并在构造函数内解析或拒绝它

    我想用 ES6 语法扩展原生 Javascript Promise 类 并且能够在子类构造函数中调用一些异步函数 根据异步函数结果 承诺必须被拒绝或解决 然而 当then函数被称为 子类构造函数执行两次 抛出 未捕获的类型错误 Promis