只是为了好玩/学习我想扩展Promise,并通过stackoverflow上令人难以置信的知识人员发现,无法使用标准的旧语法。但我还是想,所以我想创建自己的IPromise类,它组成一个Promise对象,并允许其他人使用旧的非ES6语法继承它。
我想知道这个实现与内置Promise可直接继承的Universe有何不同,如果有人有洞察力,为什么内置Promise的实现者不允许继承旧语法。
这是我的可扩展/可继承的IPromise类:
// Inheritable Promise
IPromise = function(executor) {
this.promise = new Promise(executor);
};
IPromise.prototype = Object.create(Promise.prototype);
IPromise.prototype.constructor = IPromise;
IPromise.prototype.catch = function(fail) {
return this.promise.catch(fail);
}
IPromise.prototype.then = function(success, fail) {
return this.promise.then(success, fail);
};
// Usage
// No different to builtin Promsise
(new IPromise(function(resolve, reject) { return resolve(true); }))
.then(function(response) {
console.log('IPromise then is like Promise then', response);
})
.catch(function(error) {
console.log('IPromise catch is like Promise catch', error);
});
这是一个为批量ajax扩展它的示例,它等待所有请求完成,无论它们是否有任何失败。与内置功能略有不同。
// Inheriting
// You can inherit from IPromise like you would any normal class.
BatchAjax = function(queries) {
var batchAjax = this;
this.queries = queries;
this.responses = [];
this.errorCount = 0;
IPromise.call(this, function(resolve, reject) {
batchAjax.executor(resolve, reject);
});
};
BatchAjax.prototype = Object.create(IPromise.prototype);
BatchAjax.prototype.constructor = BatchAjax;
BatchAjax.prototype.executor = function(resolve, reject) {
var batchAjax = this;
$.each(this.queries, function(index) {
var query = this;
query.success = function (result) {
batchAjax.processResult(result, index, resolve, reject);
};
query.error = function (jqXhr, textStatus, errorThrown) {
batchAjax.errorCount++;
var result = {
jqXhr: jqXhr, textStatus: textStatus, errorThrown: errorThrown
};
batchAjax.processResult(result, index, resolve, reject);
};
$.ajax(query);
});
};
BatchAjax.prototype.processResult = function(result, index, resolve, reject) {
this.responses[index] = result;
if (this.responses.length === this.queries.length) {
if (this.errorCount === 0) {
resolve(this.responses);
} else {
reject(this.responses);
}
}
};
// Usage
// Inheriting from IPromise is boring, which is good.
var baseUrl = 'https://jsonplaceholder.typicode.com';
(new BatchAjax([{url: baseUrl + '/todos/4'}, {url: baseUrl + '/todos/5'}]))
.then(function(response) {console.log('Yay! ', response);})
.catch(function(error) {console.log('Aww! ', error);});
请记住,我只是在学习,这并不意味着有用,只是有趣。但是随意给予残酷的批评,我对这是一个愚蠢的事情这个想法持开放态度。)
干得好看,对所有代码感到抱歉!
编辑:这是我最初试图延长承诺的问题:Extending a Promise in javascript。它似乎不适用于旧语法,因为Promise构造函数如果注意到它正在初始化一些不是Promise的东西(我认为),则抛出一个Type错误。
edit2:jfriend00的评论突出了一些有趣的内容。 IPromise.then应该返回什么?目前它只是一个承诺,但它应该是一个IPromise吗?
IPromise.prototype.then = function(success, fail) {
this.promise.then(success, fail);
return new IPromise(whatGoesHere?);
};
或者任何类继承自它的实例。
IPromise.prototype.then = function(success, fail) {
this.promise.then(success, fail);
return new this.constructor(whatGoesHere?);
};
或者它可以归还吗?
IPromise.prototype.then = function(success, fail) {
this.promise.then(success, fail);
return this;
};
我知道Promise.then返回一个Promise,但我不知道Promise是如何设置或预期的。这就是为什么我避免了这个问题,只是从this.promise.then返回了Promise。还有其他合理的解决方案吗?
答案 0 :(得分:2)
是的,您的IPromise
行为与真实Promise
大致相同。但是,例如,你不能在它们上调用原生的promise方法:
var p = new Promise(function(resolve) { return resolve(true); });
var ip = new IPromise(function(resolve) { return resolve(true); });
Promise.prototype.then.call(p, v => console.log(v));
Promise.prototype.then.call(ip, v => console.log(v)); // TypeError
如果您希望IPromise
个实例成为真正的承诺,则必须由Promise
进行初始化。该构造函数添加了一些内部插槽,如[[PromiseState]],您无法模拟。但是Promise
创建的承诺继承自Promise.prototype
,而在ES6之前,在创建对象之后没有标准的方法将[[Prototype]]更改为IPromise.prototype
。
使用ES6课程,
class IPromise extends Promise {
// You can add your own methods here
}
答案 1 :(得分:0)
以下是jfriend00的评论建议。
当你链接IPromises时,你不会在链接后获得一个IPromise对象,因为你的IPromise.prototype.then()
只返回一个普通的Promise return this.promise.then(success, fail);
我:应该IPromise.then只是做:
this.promise.then(success, fail);
然后其中一个?
return new IPromise(whatGoesHere?); return new this.constructor(whatGoesHere?); return this;
这是延长承诺真的很麻烦的原因之一。基础结构本身会在每次.then()调用时创建新的promise,并且在没有支持子类化的底层基础结构的情况下,不提供一种简单的方法来挂钩。如果你看here某些环境中存在支持。但是,我总是发现我可以通过其他方式解决我的问题。所以,我不会试图破解我自己的子类,因为它似乎可能有漏洞。
回到我身边(tobuslieven)现在又说话了。我同意这一点,但是如果我看到机会的话,我仍然会记住这个课程并使用它。我认为返回Promise而不是IPromise是可行的,能够像这样扩展Promises真的很有趣。
所以我的回答是肯定的,可能已经足够好了,值得在某个地方使用。