Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I JSDoc custom EventEmitter on events in Visual Studio Code?

I've been working on a Node.js project and only just noticed that Visual Studio Code provides information about base EventEmitter objects. So I imagine it should be possible to provide JSDoc for custom ones too.

screenshot of built-in on event

I've already attempted following the JSDoc http://usejsdoc.org/tags-event.html documentation but doesn't seem to pick up.

screenshot of custom event

I don't know if this is effecting it but I'm using the ES6 class where the events get processed in a function outside it but it's inside the same script.

This is the test code.

// voice
if (voice) {
  try {
    /**
     * Voice event.
     *
     * @event TelegramBot#voice
     * @type {object}
     * @property {object} chat - [object Chat]
     * @property {number} date - Date when content was sent.
     * @property {object} from - [object User]
     * @property {number} message_id - Message id.
     * @property {string} caption - Caption added to message. Value is undefined if none is added.
     * @property {object} voice - [object Voice]
     */
    context.emit('voice', chat, date, from, message_id, caption, voice)
  } catch (error) {
    context.emit('error', error)
  }
}
like image 251
Nova Avatar asked Oct 31 '17 21:10

Nova


People also ask

What happens if an error event is emitted through an EventEmitter and nothing listens to it?

Any listeners for the error event should have a callback with one argument to capture the Error object and gracefully handle it. If an EventEmitter emits an error event, but there are no listeners subscribed for error events, the Node. js program would throw the Error that was emitted.

How do I add a listener to EventEmitter?

on(event, listener) and eventEmitter. addListener(event, listener) are pretty much similar. It adds the listener at the end of the listener's array for the specified event. Multiple calls to the same event and listener will add the listener multiple times and correspondingly fire multiple times.

What is event emitter for?

[...] EventEmitter is really an Angular abstraction, and should be used pretty much only for emitting custom Events in components. Otherwise, just use Rx as if it was any other library. This is stated really clear in EventEmitter's documentation. Use by directives and components to emit custom Events.

What is the return type of EventEmitter listeners event )?

The return value of event handlers is completely ignored. From the documentation: When the EventEmitter object emits an event, all of the functions attached to that specific event are called synchronously. Any values returned by the called listeners are ignored and will be discarded.


1 Answers

I found this question while attempting to do the same, so I kept searching and I found a possible solution, by overriding the addListener methods, and documenting them.

I successfully made it work for both NodeJS and browser JS.

Result in VSCode

enter image description here

Typedef

First, create the typedef with your events names :

/**
 * @typedef {["someEvent" | "someOtherEvent", ...any[]]} eventsDef
 */

I am using the spread syntax since I don't know how many arguments the user will pass to the method.

Implementation

For NodeJS:

The class needs to override the on and addListener methods, document the arguments, and simply call the parent's own method :

class Test extends EventEmitter {

  /**
   * @param {eventsDef} args
   */
  addListener(...args) {
    super.addListener(...args);
  }

  /**
   * @param {eventsDef} args
   */
  on(...args) {
    super.on(...args);
  }

  fireEvent() {
    this.emit("someEvent", "someValue");
  }
}

Then you can use this class like so :

const t = new Test();

t.on("someEvent", (val) => console.log(val));

t.fireEvent(); // Outputs "someValue"

For the browser:

The class needs to extends EventTarget and override the addEventListener method.

Here is the snippet :

class Test extends EventTarget {
  /**
   * @param {["someEvent" | "someOtherEvent", ...any[]]} args
   */
  addEventListener(...args) {
    super.addEventListener(...args);
  }
  
  fireEvent() {
    this.dispatchEvent(new CustomEvent("someEvent", {detail: "someValue"}))
  }
}

const t = new Test();

t.addEventListener("someEvent", val => console.log(val.detail));


document.querySelector("button").addEventListener("click", () => {
  t.fireEvent();
})
<button>Fire event</button>
like image 180
Seblor Avatar answered Oct 22 '22 23:10

Seblor