扩大承诺以支持进度报告

所以我想扩展Promise有一个“进步”的一部分,以便我可以使用Promise为我的Async任务报告progrss。

因此,我延续了这样的承诺:

class promisePro extends Promise { constructor(fn) { super(function (resolve, reject) { fn(resolve, reject, this._progress.bind(this)); }); } _progress(v) { if (this.progressCB) this.progressCB(v); } progress(fn) { this.progressCB = fn; } } 

并用它:

 function ptest() { return new promisePro((resolve, reject, progress) => { setTimeout(() => { progress(0.3) }, 1000) setTimeout(() => { progress(0.6) }, 2000) setTimeout(() => { progress(0.9) }, 3000) setTimeout(() => { resolve(1) }, 4000) }) } 

并使用它:

 ptest().then((r) => { console.log('finiished: ' + r) }).progress((p) => { console.log('progress: ' + p) }) 

并得到这个错误:

 ptest().then((r) => { ^ TypeError: Promise resolve or reject function is not callable 

我在这里做错了什么?

我正在使用节点7.5,更新到8.4。 在两个版本中都有这个错误。

谢谢。

这里有几个问题需要注意。

首先,在超级函数被调用之前,“this”关键字是未定义的。 因此你可以改变构造函数到下面的东西,使用一个函数来引用一个实例化的variablessel

 constructor(fn) { let self; super(function (resolve, reject) { fn(resolve, reject, value => self._progress(value)); }); self = this; } 

其次,记住你正在扩展promisetypes,所以当你调用它的“then”函数时,它将返回一个新的 promise对象,而不是你的新的promisetypes,所以进程函数在那里是未定义的。 一种避免这种情况的方法是在进度函数中返回“this”,并在之前的用法中使用进度函数,如下

 progress(fn) { this.progressCB = fn; return this; } 

和用法

 ptest().progress((p) => { console.log('progress: ' + p) }).then((r) => { console.log('finiished: ' + r) }) 

但是现在你将失去承诺的好处,并且不能将更多的承诺与进展联系起来(仍然取决于你的使用情况)。

作为一个不同的方法build议,你有没有尝试过使用Observables? http://reactivex.io/rxjs/