扩大承诺以支持进度报告
所以我想扩展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/