EventEmitter3 模块的使用经验及骚操做

前言

EventEmitter3 模块是一款通过优化的高性能 EventEmitter,而 EventEmitter 是一种发布/订阅模式的实现方式,经过使用 EventEmitter 咱们可以在前端代码中建立自定义的事件机制。前端

EventEmitter3 模块同时兼融 NodeJS浏览器npm

使用 EventEmitter3

安装

npm install EventEmitter3 --save
复制代码

引用

var EE = new EventEmitter()
  , context = { foo: 'bar' };
 
function emitted() {
  console.log(this === context); // true
}

// 订阅
EE.once('event-name', emitted, context);    // 只订阅一次
EE.on('another-event', emitted, context);   // 持续订阅
EE.removeListener('another-event', emitted, context);   // 移除现有的订阅
复制代码

骚操做

配合 Promise/async&await 封装同步代码

在咱们编写复杂的逻辑时,可能会受制于框架、上下文、工具只能采起异步的编码,而为了提升事务调度器的代码可读性,咱们能够经过 EventEmitter + Promise + async&await 来将主逻辑代码以同步的方式编写在同一个上下文、代码块中。 例如笔者在使用 React Hooks 编写一些复杂的组件时,由于 useState 返回的更新函数并不像 Class组件的 SetState 同样提供新状态已被成功渲染的回调函数,因此只能配合 useEffect 来处理渲染完成的信号。但这样子咱们的逻辑代码会被迫拆分到了多个代码块中,致使代码过于复杂,可读性、维护性都下降,例如如下代码:canvas

function MyComponent() {
  const [size, setSize] = useState({
    width: 0,
    height: 0
  });
  useEffect(() => {
    // 在这里对 canvas 进行 draw 的操做才是安全的
  }, [size]);
  return (
    <div> <button onClick={() => { setSize({ width: 100, height: 100 }); // 这里对 canvas 进行 draw 等操做可能不安全,由于此时 Size 变动后并无实际应用到 dom 中,因此极可能会 draw 后 dom 中的 canvas 会从新渲染,而 canvas 从新渲染后其中绘制的内容会被重置。 }}>init canvas</button> <canvas style={{ width: `${size.width}px`, height: `${size.height}px` }}></canvas> </div>
  )
} 
复制代码

接下来,让咱们优化咱们的代码:浏览器

const EE = new EventEmitter();

function MyComponent() {
  const [size, setSize] = useState({
    width: 0,
    height: 0
  });
  // 封装同步更新方法
  const setSizeSync = (value) => {
    setSize(value);
    return new Promise(resolve => {
      EE.once('onSizeChange', resolve);     // 订阅一次 "onSizeChange" 事件
    });
  }
  useEffect(() => {
    EE.emit('onSizeChange');    // 触发 "onSizeChange" 事件
  }, [size]);
  return (
    <div> <button onClick={async () => { await setSizeSync({ width: 100, height: 100 }); // 如今这里能够安全的使用 CanvasContext 对 Canvas 进行操做了 }}>init canvas</button> <canvas style={{ width: `${size.width}px`, height: `${size.height}px` }}></canvas> </div>
  )
} 
复制代码
相关文章
相关标签/搜索