Skip to content

期约进度通知 ​

本节目标:理解“期约进度通知”的核心思路,并能把它用于实际开发或面试表达。 执行中的期约可以有会有不少离散的”阶段“,在最终解决之前必须依次经过。在某些情况下,监控期约的执行进度会很有用。

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) completed
nofity()函数会返回期约,所以可以链式调用,连续添加处理程序。多个处理程序会针对每条消息分别执行一遍,如下所示:
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

总体来看,这还是一个比较粗糙的实现,但应该可以演示出如何使用通知报告进度了;

本站总访问 — 次