Javascript 无法重写Promise类上的方法-Promise.prototype.then在未定义的不兼容接收器上调用

Javascript 无法重写Promise类上的方法-Promise.prototype.then在未定义的不兼容接收器上调用,javascript,node.js,promise,postman,es6-promise,Javascript,Node.js,Promise,Postman,Es6 Promise,我试图覆盖然后,捕获和最后函数。这是为了创建一个全局计数器并监视待定的承诺 代码需要在Postman沙箱中执行,因此我不能使用任何NPM模块。我需要用原生JS来实现这一点 下面是我正在努力解决的代码 _constructor = Promise.prototype.constructor _then = Promise.prototype.then Promise.prototype.constructor = (...args) => { console.log("Promis

我试图覆盖
然后
捕获
最后
函数。这是为了创建一个全局计数器并监视待定的承诺

代码需要在Postman沙箱中执行,因此我不能使用任何NPM模块。我需要用原生JS来实现这一点

下面是我正在努力解决的代码

_constructor = Promise.prototype.constructor
_then = Promise.prototype.then

Promise.prototype.constructor = (...args) => {
    console.log("Promise constructor called")
    let data = _constructor(...args)
    console.log("Promise constructor finished")
    return data;
}

Promise.prototype.then = (...args) => {
    console.log("then called")
    let data = _then.call(this, args)
    console.log("then finished")
    return data;
}

function test2(num) {
    let promise = new Promise((resolve, reject) => {
        if (num > 1) {
            setTimeout(()=> {
                resolve(num)
            }, 10)
        } else {
            reject(num);
        }
    });
    return promise
}

test2(10).then((num) => {
    console.log("Inside then")
    setTimeout(() => console.log("Promise has been resolved - " + num), 20);
})
但当我运行这个程序时,我得到了以下错误

    let data = _then.call(this, args)
                     ^

TypeError: Method Promise.prototype.then called on incompatible receiver #<Object>
    at Object.then (<anonymous>)
    at Promise.then.args (/Users/tarun.lalwani/Desktop/test/postman/temp.jsx:15:22)
    at Object.<anonymous> (/Users/tarun.lalwani/test/postman/temp.jsx:33:11)
    at Module._compile (module.js:660:30)
    at Object.Module._extensions..js (module.js:671:10)
    at Module.load (module.js:573:32)
    at tryModuleLoad (module.js:513:12)
    at Function.Module._load (module.js:505:3)
    at Function.Module.runMain (module.js:701:10)
    at startup (bootstrap_node.js:193:16)
let data=\u then.call(this,args)
^
TypeError:方法Promise.prototype.then在不兼容的接收器上调用#
at Object.then()
在Promise.then.args(/Users/tarun.lalwani/Desktop/test/postman/temp.jsx:15:22)
反对。(/Users/tarun.lalwani/test/postman/temp.jsx:33:11)
在模块处编译(Module.js:660:30)
在Object.Module.\u extensions..js(Module.js:671:10)
在Module.load(Module.js:573:32)
在tryModuleLoad时(module.js:513:12)
在Function.Module.\u加载(Module.js:505:3)
位于Function.Module.runMain(Module.js:701:10)
启动时(bootstrap_node.js:193:16)
我不确定这里出了什么问题,或者这是正确的方式还是错误的

在arrow函数中,这将保留封闭词法的值 就是这样。在全局代码中,它将被设置为全局对象

你需要改变

Promise.prototype.constructor = (...args) => {
    console.log("Promise constructor called")
    let data = _constructor(...args)
    console.log("Promise constructor finished")
    return data;
}

Promise.prototype.then = (...args) => {
    console.log("then called")
    let data = _then.call(this, args)
    console.log("then finished")
    return data;
}
进入


这方面有很多问题:

  • newpromise
    将调用
    Promise
    ,而不是被重写的
    Promise.prototype.constructor
  • 箭头函数不是构造函数。使用
    new
    调用时,它们将抛出
  • 调用
    \u构造函数
    (即内置的
    承诺
    )而不调用
    新的
    ,将抛出
  • 箭头函数不是方法。它们有一个词法
    this
    值,而不是一个动态接收器
  • 您希望
    应用
    参数,而不是
    调用它们,或者使用扩展语法
您可以通过正确地使用
函数
s和
反射
对象来解决这些问题,但是我想使用ES6子类化更简单:

Promise = class extends Promise {
    constructor(...args) {
        console.log("Promise constructor called")
        let data = super(...args)
        console.log("Promise constructor finished")
        return data;
    }
    then(...args) {
        console.log("then called")
        let data = super(...args)
        console.log("then finished")
        return data;
    }
};

当然,这里的任何内容实际上都无法确定承诺何时挂起。

@Tarun Lalwani,您不能像上面那样重写承诺构造函数,因为承诺是一个类而不是一个函数。正如@Bergi所提到的,您需要使用Reflect来拦截承诺构造函数

这里的问题是ES6类(例如Promise)是不可调用的,就像ES5内置类(例如Array)一样。编译器生成的发出代码使用ES6引擎中抛出的super.call

这里的修复方法是使用Reflect.construct(如果存在),而不是调用。Reflect.construct不是我们可以填充的东西,但我们可以假设如果存在内置承诺,Refelect.construct也存在


在上面的链接中,提到了如何扩展构造函数。通过这样做,您可以在调用
new Promise()

时打印
console.log(“Promise constructor called”)
,感谢
then
函数现在可以工作了,但是
console.log(“Promise constructor called”)
仍然没有被记录。我使用了
新承诺(…)
。我在这一部分遗漏了什么?请阅读,我只是在阅读,并准备在这里发布链接:-)。感谢您的帮助此代码有问题,如果您重写“then”并在“then”中调用它,那么您将无法在_then.call(this,args)上进行等待,因为您将运行无限递归调用。这意味着您无法跟踪挂起的承诺,因为您的函数是同步的,没有等待异步调用的能力。你需要做的是创建一个新的函数,比如“myThen”,它会扭曲,而不是重写它。你是对的,它有一个递归问题。我没有使用任何解决方案,因为它最终成为一名邮递员
Promise = class extends Promise {
    constructor(...args) {
        console.log("Promise constructor called")
        let data = super(...args)
        console.log("Promise constructor finished")
        return data;
    }
    then(...args) {
        console.log("then called")
        let data = super(...args)
        console.log("then finished")
        return data;
    }
};