Open juandopazo opened 11 years ago
I've been doing object-side prototypal inheritance in Chai as Promised. Basically:
function createExtendedPromise(promise) {
var extendedPromise = Object.create(promise);
extendedPromise.extraMethod = function () { };
return extendedPromise;
}
This was somewhat necessary due to Q promises being frozen (and thus non-extensible).
I've sometimes used promises as a mixin:
function FluentAPI() {
let {promise, resolver} = defer();
this.then = function () {
//start request
//then delegate to real then
return promise.then.apply(promise, arguments);
};
//done calls this.then anyway
this.done = promise.done;
}
Which is necessary if you want a fluent API:
Request()
.post(url)
.with(data)
.then(function (res) {
});
I'm leaning towards saying we should go with Promise(fn)
as a constructor, partly because it makes it really easy to do sane inheritance and extension of promise objects. With that in mind, we need to be very careful in the Promise constructor. This, for example, doesn't work:
function PromiseA(fn) {
fn('RESOLVER_GOES_HERE');
this.then = ...;
}
function PromiseB(fn) {
PromiseA.call(this, fn);
}
PromiseB.prototype = new PromiseA();
PromiseB.prototype.constructor = PromiseB;
new PromiseB(function () {});
If we add a check for typeof fn === 'function'
in the PromiseA constructor everything works great. We could then add all our extensions to B's prototype.
I think if we think it's desirable to have our promises frozen (as Q does) we should probably require people to instead do something like:
function PromiseA(fn) {
fn('RESOLVER_GOES_HERE');
this.then = ...;
}
function PromiseB(fn) {
PromiseA.call(this, fn);
}
PromiseB.prototype = Object.create(PromiseA.prototype);
PromiseB.prototype.constructor = PromiseB;
new PromiseB(function () {});
Two key points to note about this:
constructor
of PromiseB.prototype
is essential in order for #5 to be possible.This also lets you extend the resolver object by wrapping fn in something which extends the resolver.
@ForbesLindesay Breaks because of lack of Object.create()
? There's the Object.create()
polyfill for that. Though not fully feature compatible, it seems pragmatically appropriate here. I haven't done Y.prototype = new X();
in years :)
Yes, Object.create
can be polyfilled sufficiently as:
function create(obj) {
function F() {}
F.prototype = obj;
return new F();
}
Promise objects have only the
then
method and maybe a few other utility methods. But using promises for chaining asynchronous operations require more complex objects. For instance, jQuery'sanimate
method should return a promise with ananimate
method so you can do$(selector).animate(opts1).animate(opts2)
.I see two basic approaches to this: prototypical inheritance or "parasitic" inheritance (copying properties). How have you folks been dealing with this? What have you learned so far? Would you do anything differently?