期约进度通知的实现
class TrackablePromise extends Promise {
//executor是一个函数
constructor(executor) {
const notifyHandlers = [];
super((resolve, reject) => {
const notify = (status) => {
notifyHandlers.map((handler) => {
console.log("运行处理信息的函数");
handler(status);
});
};
return executor(resolve, reject, notify);
});
this.notifyHandlers = notifyHandlers;
}
notify(notifyHandler) {
this.notifyHandlers.push(notifyHandler);
return this;
}
}
let p = new TrackablePromise((resolve, reject, notify) => {
function countdown(x) {
if (x > 0) {
notify(`${20 * x}% remaining`);
setTimeout(() => countdown(x - 1), 500);
} else {
resolve();
}
}
countdown(5);
});
p.notify((msg) => console.log(`第一个信息处理函数:` + msg));
p.then(() => setTimeout(console.log, 0, "completed"));
TrackablePromise继承了Promise,并添加了新的功能,能够对Promise中的异步任务进行期约内部的进度通知。 具体的做法是:
- 创造TrackablePromise实例,Super传入两个Promise构造参数,resolve及reject,在原始的promise构造参数中声明notify函数。将其与原始的resolve,reject参数传入executor中,并返回调用executor产生的返回值,即TrackablePromise的实例。
其中:notify函数将notifyHandlers列表中的每个通知的具体行为进行进一步处理,将传给notify的参数进一步传入到内部的具体行为中,后续在异步代码中通过notify()调用该函数。
- 在实例中声明notifyHandlers列表,初始值为空列表。内部存储的是异步任务在处理过程中有关进度通知的具体行为,如:打印目前所运行的进度信息。
- 在异步任务的运行中,如需通知进度,则在合适的位置加入notify。
上面的代码功能已总结完毕,由于上部分代码中较为复杂,分析一下语法。
- 由于resolve, reject经常接触,需要在Promise实例中传入(resolve,reject)=>{},这部分极为熟悉,但是当需要传入第三个notify参数时就需要在super中进行修改。super接收的是TrackablePromise的实例构造函数,在super中声明notify即可,而后送入至构造TrackablePromise函数中。
- notify返回this,可以实现链式调用。
- 调用 super()会调用父类构造函数,并将返回的实例赋值给 this,对理解 return executor(resolve, reject, notify);有所帮助
在计数的过程中加入期约进度通知
let p = new TrackablePromise((resolve, reject, notify) => {
let number = 0;
let total = 5;
// 方法1
// const id = setInterval(() => {
// if (number > total) {
// clearInterval(id);
// resolve();
// }
// number = number + 1;
// notify(number);
// }, 1000);
// 利用闭包
for (let i = 0; i < 10; i++) {
(function (i) {
setTimeout(() => {
notify(i);
}, 1000);
})(i);
}
});
p.notify((msg) => console.log(msg));
p.then(() => setTimeout(console.log, 0, "completed"));