protobuf.js icon indicating copy to clipboard operation
protobuf.js copied to clipboard

fix: fix the unexpected case when listener be triggered

Open benmix opened this issue 3 years ago • 2 comments

Fix the unexpected case when listener be triggered. When I add two listeners of the same type to the event-emitter, and then I remove the first listener in the first listener's handler, the second listener cannot be executed correctly.

benmix avatar Sep 08 '22 22:09 benmix

If I'm reading the code correctly, it requires copying the list of listeners every time an event is emitted, which is probably a lot of extra work for just a simple use case. I'm guessing the workaround could be to postpone the invocation of .off() to the next event loop iteration:

ee.on("event", () => {
  ...
  setImmediate(() => { ee.off(func); });
});

alexander-fenster avatar Sep 09 '22 15:09 alexander-fenster

If I'm reading the code correctly, it requires copying the list of listeners every time an event is emitted, which is probably a lot of extra work for just a simple use case. I'm guessing the workaround could be to postpone the invocation of .off() to the next event loop iteration:

ee.on("event", () => {
  ...
  setImmediate(() => { ee.off(func); });
});

Hi,thank you take time to review my PR 😊.

Using setImmediate is effective, but I think it is not a good way. Because sometimes we forget to use setImmediate to avoid this situation.

slice() method is shallow copy the array, the cost is acceptable 😃.

Moreover, the invocations of emit, off and on, they should not affect the execution of the previous invocation. In another case, if we listen to it self again in each on handler, the listener added later will also be affected by the last emit and triggered, which is inappropriate and will cause the infinite loop.

Showing code like below

  let fn = function () {
    /* ... do something */
    ee.on("b", fn);
  };
  ee.on("b", fn);

benmix avatar Sep 09 '22 21:09 benmix