美文网首页
手写EventHub

手写EventHub

作者: 西域战神 | 来源:发表于2020-11-21 22:11 被阅读0次

实现EventHub

image.pngimage.png

在文件1中的f1需要在某种情况下调用文件2中的f2, 用全局变量是不好的,此时可以通过创建一个EventHub,在f1中emit一个事件,然后f2接收到这个事件后,进行相应的操作。

on 和 emit

/src/index.ts

class EventHub {
  cache: { [key: string]: Array<(data: unknown) => void> } = {};


  // {'报社1':[f1,f2,f3],'报社2':[f11,f22,f33]}
  on(eventName: string, fn: (data: unknown) => void) {
    // eventName = 报社1,   fn
    if (this.cache[eventName] === undefined) {
      this.cache[eventName] = [];
    }
    const array = this.cache[eventName];
    array.push(fn);
  }
  emit(eventName:string) {
    let array = this.cache[eventName];
    if (array === undefined) {
      array = [];
    }
    array.forEach((fn) => {
      fn();
    });
  }
}

export default EventHub;

/test/index.ts

import EventHub from '../src/index';
const eventHub = new EventHub();

let called = false;
eventHub.on('xxx', () => {
  console.log('被调用');
  called = true;
  console.log('called:' + called);
});
eventHub.emit('xxx');

此时called经过eventHub的调用,顺利变为true

class EventHub {
  cache: { [key: string]: Array<(data: unknown) => void> } = {};


  // {'报社1':[f1,f2,f3],'报社2':[f11,f22,f33]}
  on(eventName: string, fn: (data: unknown) => void) {
    // eventName = 报社1,   fn
    this.cache[eventName] = this.cache[eventName] || [];
    this.cache[eventName].push(fn);
  }
  emit(eventName: string, data?: unknown) {
    (this.cache[eventName] || []).forEach((fn) => fn(data));
  }
}

export default EventHub;

简化emit和on中的逻辑,通常情况下emit中还需传递一个data的参数,我们通过在on中console.assert来断言data的顺利传递

import EventHub from '../src/index';
const eventHub = new EventHub();

const test1 = () => {
  eventHub.on('xxx', (y) => {
    console.log('被调用');
    console.assert(y === 'data1');
  });
  eventHub.emit('xxx', 'data1');
};
test1()

此时,我们在on中接受的参数!== 'data1',得到了Assertion failed的错误

off操作

/test/index.ts

const test2 = () => {
  const eventHub2 = new EventHub();
  let called2 = false;
  const fn1 = eventHub2.on('yyy', () => {
    called2 = true;
  });

  eventHub2.off('yyy', fn1);

  eventHub2.emit('yyy', fn1);
  setTimeout(() => {
    console.log('--called2---');
    console.log(called2);
  }, 1000);
};
test2()

创建一个eventHub2,在监听一个事件后,马上取消该事件,called2将不会被修改

/src/index.ts

 off(eventName: string, fn) {
    // 把fn从this.cache[eventName]中删除
    let index;
    this.cache[eventName] = this.cache[eventName] || [];
    for (let i = 0; i < this.cache[eventName].length; i++) {
      if (this.cache[eventName][i] === fn) {
        index = i;
        break;
      }
    }
    if (index === undefined) {
      return;
    }
    this.cache[eventName].splice(index, 1);
  }

我们从cache[eventName]中移除fn方法
此时,我们能从顺利看到called2没有被赋值为true

相关文章

网友评论

      本文标题:手写EventHub

      本文链接:https://www.haomeiwen.com/subject/cicyiktx.html