【问题标题】:Extending the built-in javascript Promise扩展内置的 javascript Promise
【发布时间】:2017-04-18 05:31:09
【问题描述】:

我正在尝试用一种新方法来扩展 javascript 承诺。在这种情况下,这个新方法称为foo,它确实做了这样的事情:

Promise.foo = function(arg) {
  return this.then( function(result) {
    return result.foo(arg);
  });
};

简而言之,foo() 函数是一个快捷方式,用于等待 promise 解决,然后在结果上调用 foo()。

这个函数的本质是可以链接,就像then()可以一样。

myPromise.foo(a).foo(b).foo(c);

我觉得这应该是可能的,但我只是不确定正确的路径是什么。

这是我尝试过的:

var FooPromise = function() {
   Promise.apply(this, arguments);
}

FooPromise.prototype = Object.create(Promise.prototype);
FooPromise.foo = function(arg) {
  return this.then( function(result) {
    return result.foo(arg);
  });
};

测试一下:

var test = new FooPromise(function(res, rej) {
   res('bla');
});

在 Firefox 中,这给了我:

TypeError: calling a builtin Promise constructor without new is forbidden

在节点中:

TypeError: #<Promise> is not a promise

这只是javascript的限制,还是有办法解决这个问题?

【问题讨论】:

  • 也许你应该使用 FooPromise.prototype.foo - 因为你将使用 FooPromise 的实例(为什么不首先将它添加到 Promise.prototype.foo 并且根本不使用 FooPromise) -至于你试图从 Promise “继承” - 它看起来有 3 种错误开始
  • 什么是result.foo
  • 显然你可以扩展Promise而不使用@anete.anetes显示的ES6 class FooPromise extends Promise语法,因为Promise会检查new.target是否被调用作为构造函数 - 如果不是,ECMA 规范中要求它抛出错误。
  • @JaromandaX 因为我只想在我的库的上下文中对其进行“子类化”,我不想做一个全局猴子补丁,因为我认为通常这是一种不好的做法。

标签: javascript promise


【解决方案1】:

ES6方式:

class FooPromise extends Promise {
    constructor(executor) {
        super(executor);
    }
}

var fooPromise = new FooPromise((resolve,reject)=>{
   resolve(null);
});

【讨论】:

  • TypeError:promise 的执行者必须是一个函数。
  • 当然!您需要实现基本的构造函数参数)例如:var fooPromise = new FooPromise((resolve,reject)=&gt;{resolve(1);});
  • 谢谢,太好了!我认为这是唯一的方法吗?仍然有点担心在浏览器中使用 ES6 语法,但也许我需要停止担心 =)
  • 我的选择是typescript
  • @user4074041 如果我需要在子类构造函数中解决或拒绝我的扩展承诺怎么办?在提供的解决方案中,无法访问解决/拒绝功能。
【解决方案2】:

经过更多研究,我找到了以下解决方案。无需扩展内置的 Promise。您真正需要的是确保您的对象正确实现 then(又名 Promise/A+ / thenable)。

function FooPromise(executor) {

  this.innerPromise = new Promise(executor);

}

FooPromise.prototype = {

 then: function(onFulfilled, onRejected) {

    return new FooPromise(function(res, rej) {

       this.innerPromise.then(res, rej);

    });

  },

  foo: function() {

    return this.then(function(val) {

      return val.foo();

    });

  }

}

这在 ES5 环境中运行良好,与其他 Promise 甚至 async/await(如果可用)完美配合。

我成功实现了这个模式this open source library

【讨论】:

  • 我喜欢 4 年的 JS 开发者我第二次猜测这是否是另一种记录不充分的定义对象的方式,或者只是糟糕的语法。不过,我 99% 确信这是一种糟糕的语法。
  • @gbtimmon: edit 我看到了问题。忽略最后的评论
  • 别忘了也实现 catch & finally,这也是 Promise 消费者期望存在的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-11-27
  • 2015-06-02
  • 2010-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多