用javascript扩展承诺

用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

我正在学习javascript中的类和继承。我认为以下是扩展现有对象的一种相当标准的方法,因为我从

我期待着看到“好”然后是“耶!控制台中的“Hello”,但我出现以下错误:

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)