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>
  )
} 
複製代碼
相關文章
相關標籤/搜索