preface

The EventEmitter3 module is an optimized high-performance EventEmitter, which is a publish/subscribe implementation that allows you to create custom event mechanisms in front end code.

The EventEmitter3 module incorporates both NodeJS and a browser

useEventEmitter3

The installation

npm install eventEmitter3 --save
Copy the code

reference

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

/ / subscribe
EE.once('event-name', emitted, context);    // Subscribe only once
EE.on('another-event', emitted, context);   // Continue to subscribe
EE.removeListener('another-event', emitted, context);   // Remove an existing subscription
Copy the code

SAO operation

Encapsulate synchronous code with Promise/ Async&await

When we write complex logic, we may be constrained by the framework, context, and tools to code asynchronously, but to improve the readability of the transaction scheduler code, We can use EventEmitter + Promise + Async&await to write the main logic code synchronously in the same context, code block. For example, when I used React Hooks to write some complex components, the update function returned by useState did not provide the callback function that the new state had been successfully rendered like the SetState of the Class component, so the useEffect could only be used to handle the signal that the rendering had completed. However, in this way, our logical code will be forced to split into multiple code blocks, resulting in overly complex code, which reduces readability and maintainability, such as the following code:

function MyComponent() {
  const [size, setSize] = useState({
    width: 0.height: 0
  });
  useEffect((a)= > {
    // It is safe to draw the canvas here
  }, [size]);
  return (
    <div>
      <button onClick={()= >{ setSize({ width: 100, height: 100 }); // It may not be safe to draw the canvas, because the Size change is not actually applied to the DOM, so it is likely that the canvas in the DOM will be re-rendered after draw, and the contents drawn in the canvas will be reset after re-rendered. }}>init canvas</button>
      <canvas style={{ width:` ${size.width}px`, height:` ${size.height}px` }}></canvas>
    </div>)}Copy the code

Next, let’s optimize our code:

const EE = new EventEmitter();

function MyComponent() {
  const [size, setSize] = useState({
    width: 0.height: 0
  });
  // Encapsulate the synchronous update method
  const setSizeSync = (value) = > {
    setSize(value);
    return new Promise(resolve= > {
      EE.once('onSizeChange', resolve);     // Subscribe once for the "onSizeChange" event
    });
  }
  useEffect((a)= > {
    EE.emit('onSizeChange');    // Trigger the "onSizeChange" event
  }, [size]);
  return (
    <div>
      <button onClick={async() = >{ await setSizeSync({ width: 100, height: 100 }); It is now safe to use CanvasContext on Canvas}}>init Canvas</button>
      <canvas style={{ width:` ${size.width}px`, height:` ${size.height}px` }}></canvas>
    </div>)}Copy the code