djipco / webmidi

Tame the Web MIDI API. Send and receive MIDI messages with ease. Control instruments with user-friendly functions (playNote, sendPitchBend, etc.). React to MIDI input with simple event listeners (noteon, pitchbend, controlchange, etc.).
Apache License 2.0
1.52k stars 115 forks source link

`removeListener` not working #317

Closed PromethiumL closed 1 year ago

PromethiumL commented 1 year ago

Describe the bug and how to reproduce it

removeListener executed without error, but listeners for noteon still exist.

Environment Operating system: Debian Testing Browser: Chrome 106.0.5249.119 (Official Build) (64-bit) Library version: webmidi@3.0.22

Almost the same as #131. Except for this time, the disable() can work normally.

Minimal Working Example:

<script src="https://cdn.jsdelivr.net/npm/webmidi@latest/dist/iife/webmidi.iife.js"></script>
<html>
<body onload="initWebMidi()">
<button onclick="removeListener()">RemoveListener</button>
</body>
</html>

<script>
  function noteOn (e) {
    console.log('noteon event')
  }

  function handler (err) {
    if (err) {
      console.error(err)
    } else {
      const input = WebMidi.inputs[0]
      input.addListener('noteon', 'all', noteOn)
      console.log('Listener added.')
      console.log('Enabled.')
    }
  }

  function initWebMidi () {
    WebMidi.enable(handler)
  }

  function removeListener () {
    WebMidi.removeListener()
    // WebMidi.disable()
    console.log('All listeners should be removed.')
  }
</script>
djipco commented 1 year ago

The removeListener() method removes all listeners that were added to the object upon which it is called. In other words, calling WebMidi.removeListener() will remove all listeners that were added to the WebMidi object.

Listeners added to a specific input need to be removed from that same input. In your example, you would have to use something like this to remove listeners from input 0:

WebMidi.inputs[0].removeListener();

Even though this is usually how the observer pattern is handled by event listener libraries, your issue tells me that the documentation is not clear enough. The documentation for removeListener() comes from the djipevents library (which WebMidi and various other objects extend). To be safe, I have created an issue so I do not forget to update the documentation.