Tiny-Event-Manager 安全轻量的资源管理器

458 阅读2分钟

在我开始写直播播放器的时候,由于需要做到最小依赖没有使用第三方的库来管理我的资源,这时候发现我对其的依赖已经到了那么严重。对于普通的应用,下面这套模型应该能够帮助我们统一处理资源问题。 除了promise。

我出现问题的代码

transaction() {
  this.timer = setTimeout(() => {
    // do something
  });

  this.interval = setInterval(() => {
     // do something
  });

   window.addEventListener('click', () => {
     // oncelogic
   })
}

componentWillUnMount() {
  if (this.timer) clearTimeout(this.timer);
  if (this.interval) clearInterval(this.interval);
  window.removeEventListener(...);
}

在一个组件的生命周期内我可能使用了很多类型的资源,但是对于资源的管理却是相当混乱,每一种资源的创建都对应一个特定的释放逻辑。我需要一种统一的模型去处理这些。

所以如果我们用下面这一套模型就会简单很多。

function createTimeout(callback, timeout) {
   const timer = setTimeout(callback, timeout);
   return () => clearTimeout(timer);
}

function createEventListener(target, type, listener) {
  function fun(...args) {
    listener.apply(this, args);
  }
  target.addEventListener(type, fun);
  return () => target.removeEventListener(type, fun);
}

这样我们将所有资源的释放逻辑都统一了,我们可以将所有类型的资源都保存在一个数组中,然后统一释放,不需要关心某个资源的释放逻辑。

但是这个模型并不能保证资源只被释放一次,因为组件可以随时释放某些逻辑,所以我们需要一个guard变量来标记是否一个资源已经被释放。

class Subscription {
  constructor(teardown) {
   if (teardown instanceof Subscription) {
     return teardown;
   }
   this.teardown = teardown;
   this.disposed = false;
  this._subs = [];
  }

  add(subOrteardown) {
   this._subs = [...this._subs, new Subscription(subOrTeardown)];
  }

  remove(sub) {
    this._subs = this._subs.filter(i => i !== sub);
  }

  unsubscribe() {
    if (!this.disposed && this.teardown) {
       this.disposed = true;
       this.teardown();
    }
    this._subs.forEach(sub => sub.unsubscribe());
  }
}

这样将所有资源的释放逻辑转换为Subscription

function createTimeout(callback, timeout) {
   const timer = setTimeout(callback, timeout);
   return new Subscription(() => clearTimeout(timer));
}

function createEventListener(target, type, listener) {
  function fun(...args) {
    listener.apply(this, args);
  }
  target.addEventListener(type, fun);
  return new Subscription(() => target.removeEventListener(type, fun));
}

程序中就可以统一管理了。

transaction() {
   const sub1 = = createTimeout(() => {
    // do something
  });

  const sub2 = createInterval(() => {
     // do something
  });

   const sub3 = createEventListener(...);

  this.subscription.add(sub1);
  this.subscription.add(sub2);
  this.subscription.add(sub3);
}

componentWillUnMount() {
  this.subscription.unsubscribe();
}

但是对于Promise却是行不通的,因为Promise一旦创建就不可被取消,除非自己实现一套特别的Promise逻辑,这一点还真是令人头大。

上面根据这些非常清晰的概念,封装到了一个包 tiny-event-manager 中,让小型应用也能很方便地管理资源。

github.com/Qquanwei/ti…