For instance, array.map accepts a callback that returns a value.

const newArray = oldArray.map(item => doSomethingTo(item));

Promises also accept callbacks that return a value.

const requestPromise = $.ajax(...).then(res => doSomethingTo(res));

But the way I see most event emitters, they seem non-functional by design.

const emitter = new EventEmitter();

// emitter.on mutates the emitter to register event
// returns nothing in most cases.

emitter.on('SOME_EVENT', event => {

  // Do something entirely irrelevant to the emitter.
  // Do something that mutates something outside the callback.
  // Returns nothing unlike array.map and promise callbacks.
  // Return value is irrelevant to the caller.


// Executes callbacks but return values are irrelevant.
// Returns nothing.


So if my understanding of functional programming is correct, event emitter callbacks aren't pure nor transparent if this is the case.

Can event emitters be written in a more functional way? Or is this a limitation of the mechanism? Are event-driven and functional incompatible? How are event emitters done in other, more functional languages?

  • 2
    If the event emitter's type is Event -> GlobalState -> GlobalState (or equivalent) then sure. – user253751 Sep 22 '16 at 2:41
  • Observable values can be used in a monadic way. – Basilevs Jan 20 '17 at 19:52

In the Redux world (which took it from the functional programming world), it works like this:

function reducer(state, action) {
   // action is the "event"
   switch (action.type) {
       case 'SOME_EVENT':
           return {...state, value: 'modified'}
           return state;

This allows your event handling to be pure. All your function does it take the current state and the event, and return a new event.

  • Redux was what I had in mind with this question. The reducer part is ok, take old state, construct new state. The part where I'm curious is the dispatch and registration phase, which are essentially like event emitters. Wondering how that part could be functional. – Joseph Sep 22 '16 at 12:57
  • 1
    @JosephtheDreamer, what about passing every single event to your reducer? There is no need to register, you simply ignore events you don't care about. There is no need to dispatch because you are already in the reducer. – Winston Ewert Sep 22 '16 at 17:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.