Extending the built-in javascript Promise

2020-07-10 09:48发布

I'm trying to extend the javascript promise with a new method. This new method in this case is called foo, which really does something like this:

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

So in short, the foo() function is a shortcut for waiting for a promise to resolve and then calling foo() on the result.

The nature of this function is that it can be chained, just like then() can.

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

I feel like this should be possible, but I'm just not sure what the right path is.

This is what I've tried:

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);
  });
};

To test it out:

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

In firefox this gives me:

TypeError: calling a builtin Promise constructor without new is forbidden

In Node:

TypeError: #<Promise> is not a promise

Is this just a limitation of javascript, or is there a way around this?

2条回答
女痞
2楼-- · 2020-07-10 10:01

After more research, I landed on the following solution. There's no need to extend the built-in Promise. All you really need is to make sure your object implements then correctly (aka 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();

    });

  }

}

This works fine in ES5 environments, works perfectly with other promises and even async/await (where available).

I successfully implemented this pattern this open source library.

查看更多
够拽才男人
3楼-- · 2020-07-10 10:23

ES6 way:

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

var fooPromise = new FooPromise((resolve,reject)=>{
   resolve(null);
});
查看更多
登录 后发表回答