用javascript扩展承诺
我正在学习javascript中的类和继承。我认为以下是扩展现有对象的一种相当标准的方法,因为我从 我期待着看到“好”然后是“耶!控制台中的“Hello”,但我出现以下错误:用javascript扩展承诺,javascript,class,oop,inheritance,promise,Javascript,Class,Oop,Inheritance,Promise,我正在学习javascript中的类和继承。我认为以下是扩展现有对象的一种相当标准的方法,因为我从 我期待着看到“好”然后是“耶!控制台中的“Hello”,但我出现以下错误: Uncaught TypeError: #<MyPromise> is not a promise at new MyPromise (<anonymous>:5:17) at <anonymous>:19:6 我最初尝试创建一个BatchAjax类,您可以使用它,如: (new Ba
Uncaught TypeError: #<MyPromise> is not a promise
at new MyPromise (<anonymous>:5:17)
at <anonymous>:19:6
我最初尝试创建一个BatchAjax类,您可以使用它,如:
(new BatchAjax([query1, query2]))
.then(function(response) {console.log('Fires when all queries are complete.');});
这真的很有趣 本机
Promise
类(如Error
和Array
)无法使用旧的ES5样式的子类化机制正确地进行子类化
子类Promise
的正确方法是通过class
语法:
class MyPromise extends Promise {
}
例如:
类MyPromise扩展了Promise{
myMethod(){
返回这个.then(str=>str.toUpperCase());
}
}
//用法示例1
MyPromise.resolve(“它起作用”)
.myMethod()
.then(result=>console.log(result))
.catch(error=>console.error(error));
//用法示例2
new MyPromise((解决、拒绝)=>{
if(Math.random()<0.5){
解决(“它起作用”);
}否则{
拒绝(新错误(“承诺被拒绝;它这样做的一半时间只是为了显示该部件工作”);
}
})
.myMethod()
.then(result=>console.log(result))
.catch(error=>console.error(error))代码>我的最新解决方案是将一个Promise对象作为this.Promise组合到我的类中,然后通过重写Promise的所有实例方法并将它们传递给this.Promise对象来假装从Promise继承。欢闹随之而来。我非常欢迎人们指出这种方法的缺点
对我来说,没有什么太明显的东西是不会错过的
当我将这段代码粘贴到Chrome控制台时,它似乎可以工作。这是我所能理解的
为看一看干杯
BatchAjax = function(queries) {
var batchAjax = this;
this.queries = queries;
this.responses = [];
this.errorCount = 0;
this.promise = new Promise(function(resolve, reject) {
batchAjax.executor(resolve, reject);
});
};
BatchAjax.prototype = Object.create(Promise.prototype);
BatchAjax.prototype.constructor = BatchAjax;
BatchAjax.prototype.catch = function(fail) {
return this.promise.catch(fail);
}
BatchAjax.prototype.then = function(success, fail) {
return this.promise.then(success, fail);
};
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
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);});
正如@tobuslieven的回答所暗示的,没有必要延长承诺。下面是一个简化的示例
ES6:
ES5:
可通过以下方式对两者进行测试:
var promise = new MyPromise()
promise.name = 'stackoverflow'
promise
.then(function () {
console.log('done!')
})
.catch(console.log)
为这个消息干杯。我不喜欢在不受支持的情况下被迫改变异常的编码风格。我们最终会得到一个令人不快的混合语法。他们应该支持原来的方式,而不是添加配料和搅拌锅。添加到复杂系统中的简化系统本身比原始复杂系统更复杂,而不是更少。人们总是犯这种错误/rant我想知道我是否可以通过在类内编写承诺而不是扩展它来绕过它。@Tobuslie即使扩展类的“原始语法”从未支持内置构造函数,也不适合这样做;这就是为什么ES6使用了一种新的方法。@Bergi My rant继续说:最初的语法不太适合任何东西,但它是语言在所有情况下都应该使用的机制(我不是很谦虚)。如果以前它不起作用,并且他们正在设计一种新版本的语言(ES6),那么他们应该对内置语言进行更改,使其能够使用旧语法。不引入替代的竞争语法。Javascript的继承语法是一条狗,现在它是两条狗。@tobuslieven:如果不破坏更改,你的建议是不可能的。在不破坏大量现有代码的情况下向前移动JavaScript是一个巨大的挑战,TC39非常重视这一挑战。关于“两条狗”--旧的语法是我们谢天谢地不再需要使用的一种技巧。没有必要继续下去。@T.J.Crowder够公平的了。令人沮丧的是,旧语法不起作用,新语法还没有得到足够广泛的支持,无法完全依赖。我想知道你对我的作文备选答案的看法。认真细致的批评是非常受欢迎的。干杯扩展Promise
的用例是什么?听起来它应该是一个简单的静态函数,返回一个正常的Promise。不需要子类化。这不是承诺吗?全部
?(但如果只是为了好玩,足够公平,实验是有教育意义的。)仅供参考,您在这里的特定用例可以很好地解决,而无需对承诺进行子类化。您所展示的示例通常被称为Promise.solite()
,并且有许多没有任何子类的实现。这里是。@tobuslieven-是的,要实现.solution()
通常的解决方案是将承诺数组添加到每个承诺中,使所有承诺都成功的.catch()
处理程序,然后将生成的承诺传递给Promise.all()
。既然他们都成功了,它会告诉你什么时候他们都成功了。实现中的变化取决于您想要什么信息,当所有关于哪些成功、哪些失败以及有哪些错误的信息都被说出来和做出来时。您想要返回的信息越简单,您可以使用的实现就越简单。我链接的答案向您展示了实现的范围。在我看来,这个答案似乎是正确的。这个策略是我发现的唯一一个支持a)调用超级构造函数并访问resolve
和reject
函数,以及b)传递instanceof Promise
检查的策略。我的用例是关于将Promise
类扩展为一个延迟的
类,该类公开其实例的解析
和拒绝
函数。我应该补充一点,尽管我认为这个答案描述了扩展Promise类的最佳方法,在99.9%的情况下,这样做可能不是最明智的。不过,如果一定要这样做,这种方法效果最好(至少根据我的测试)。我本来打算添加一些编辑建议,但是,建议的编辑队列已满,因此我必须在下面添加一个新的答案。谢谢你的灵感。
class MyPromise {
async executor () {
if(!this.name) {
throw new Error('whoops!')
}
console.log('Hello', this.name)
}
then () {
const promise = this.executor()
return promise.then.apply(promise, arguments)
}
catch () {
const promise = this.executor()
return promise.catch.apply(promise, arguments)
}
}
function MyPromise () { }
MyPromise.prototype.executor = function () {
var self = this
return new Promise(function (resolve, reject) {
if (!self.name) {
return reject(new Error('whoops!'))
}
console.log('Hello', self.name)
resolve()
})
}
MyPromise.prototype.then = function () {
var promise = this.executor()
return promise.then.apply(promise, arguments)
}
MyPromise.prototype.catch = function () {
var promise = this.executor()
return promise.catch.apply(promise, arguments)
}
var promise = new MyPromise()
promise.name = 'stackoverflow'
promise
.then(function () {
console.log('done!')
})
.catch(console.log)