Appearance
期约进度通知
本节目标:理解“期约进度通知”的核心思路,并能把它用于实际开发或面试表达。 执行中的期约可以有会有不少离散的”阶段“,在最终解决之前必须依次经过。在某些情况下,监控期约的执行进度会很有用。
ECMAScript6期约并不支持进度追踪,但可以通过扩展来实现;一种实现方式是扩展Promise类,为它添加notify()方法,如下所示:class TrackablePromise extends Promise {
constructor(executor) {
const notifyHandlers = [];
super((resolve, reject) => {
return executor(resolve, reject, (status) => {
notifyHandlers.map((handler) => handler(status));
});
});
this.notifyHandlers = notifyHandlers;
}
notify(notifyHandler) {
this.notifyHandlers.push(notifyHandler);
return this;
}
}这样,TrackablePromise就可以在执行函数中使用notify()函数了。可以像下面这样使用这个函数来实例化一个期约:
let p = new TrackablePromise((resolve, reject, notify) => {
function countdown(x) {
if (x > 0) {
notify(`${20 * x}% remaining`);
setTimeout(() => countdown(x - 1), 1000);
} else {
resolve();
}
}
countdown(5);
});这个期约会连续5次递归地设置1000毫秒的超时。每个超时回调都会调用nofify()并传入状态值。假设通知处理程序 简单地这样写:
p.notify((x) => setTimeout(console.log, 0, 'progress:', x));
p.then(() => setTimeout(console.log, 0, 'completed'));// (after 1s) 80% remaining
// (after 2s) 60% remaining
// (after 3s) 40% remaining
// (after 4s) 20% remaining
// (after 5s) completednofity()函数会返回期约,所以可以链式调用,连续添加处理程序。多个处理程序会针对每条消息分别执行一遍,如下所示:
p.notify((x) => setTimeout(console.log, 0, 'a:', x))
.notify((x) => setTimeout(console.log, 0, 'b:', x));
p.then(() => setTimeout(console.log, 0, 'completed'));
// (after 1s) a: 80% remaining
// (after 1s) b: 80% remaining
// (after 2s) a: 60% remaining
// (after 2s) b: 60% remaining
// (after 3s) a: 40% remaining
// (after 3s) b: 40% remaining
// (after 4s) a: 20% remaining
// (after 4s) b: 20% remaining
// (after 5s) completed总体来看,这还是一个比较粗糙的实现,但应该可以演示出如何使用通知报告进度了;
