# How Do I Create A Simple Event Emitter?

Publish/Subscribe is a common pattern within JavaScript applications. The idea is that you have a publisher that emits events and you have consumers which register their interest in a given event. Typically you may see something like the following where you listen for a 'data' event and then the event emitter publishes data to it.

```javascript
var emitter = new Emitter();

function logData(data) {
    console.log('data: ' + data);
}

emitter.on('data', logData);

emitter.emit('data', 'foo');
// => data: foo

// Destroy handler
emitter.off('data', logData);
```

How might one implement this using the Reactive Extensions for JavaScript? Using an `Rx.Subject` will solve this problem easily. As you may remember, an `Rx.Subject` is both an Observer and Observable, so it handles both publish and subscribe.

```javascript
var subject = new Rx.Subject();

var subscription = subject.subscribe(data => console.log(`data: ${data}`));

subject.onNext('foo');
// => data: foo
```

Now that we have a basic understanding of publish and subscribe through `onNext` and `subscribe`, let's put it to work to handle multiple types of events at once. First, we'll create an Emitter class which has three main methods, `emit`, `on` and `off` which allows you to emit an event, listen to an event and stop listening to an event.

```javascript
var hasOwnProp = {}.hasOwnProperty;

function createName (name) {
    return `$ ${name}`;
}

function Emitter() {
    this.subjects = {};
}

Emitter.prototype.emit = (name, data) => {
    var fnName = createName(name);
    this.subjects[fnName] || (this.subjects[fnName] = new Rx.Subject());
    this.subjects[fnName].onNext(data);
};

Emitter.prototype.on = (name, handler) => {
    var fnName = createName(name);
    this.subjects[fnName] || (this.subjects[fnName] = new Rx.Subject());
    this.subjects[fnName].subscribe(handler);
};

Emitter.prototype.off = (name, handler) => {
    var fnName = createName(name);
    if (this.subjects[fnName]) {
        this.subjects[fnName].dispose();
        delete this.subjects[fnName];
    }
};

Emitter.prototype.dispose = () => {
    var subjects = this.subjects;
    for (var prop in subjects) {    
        if (hasOwnProp.call(subjects, prop)) {
            subjects[prop].dispose();
        }
    }

    this.subjects = {};
};
```

Then we can use it much as we did above. As the call to `subscribe` returns a subscription, we might want to hand that back to the user instead of providing an off method. So, we could rewrite the above where we call the `on` method to `listen` and we return a subscription handle to the user to stop listening.

```javascript
var hasOwnProp = {}.hasOwnProperty;

function createName (name) {
    return `$ ${name}`;
}

function Emitter() {
    this.subjects = {};
}

Emitter.prototype.emit = (name, data) => {
    var fnName = createName(name);
    this.subjects[fnName] || (this.subjects[fnName] = new Rx.Subject());
    this.subjects[fnName].onNext(data);
};

Emitter.prototype.listen = (name, handler) => {
    var fnName = createName(name);
    this.subjects[fnName] || (this.subjects[fnName] = new Rx.Subject());
    return this.subjects[fnName].subscribe(handler);
};

Emitter.prototype.dispose = () => {
    var subjects = this.subjects;
    for (var prop in subjects) {    
        if (hasOwnProp.call(subjects, prop)) {
            subjects[prop].dispose();
        }
    }

    this.subjects = {};
};
```

Now we can use this to rewrite our example such as the following:

```javascript
var emitter = new Emitter();

var subcription = emitter.listen('data', data => console.log(`data: ${data}`);

emitter.emit('data', 'foo');
// => data: foo

// Destroy the subscription
subscription.dispose();
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://soufatn.gitbook.io/rxjs-book/summary/how_do_i/simple_event_emitter.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
