Build Your Own EventEmitter

preview_player
Показать описание

The 'Eventing' pattern in Javascript is one of the most established design mechanisms of the language. But how does eventing work behind the scenes? Learn how to build your own event emitter in this short video.

Рекомендации по теме
Комментарии
Автор

That’s pretty good, this seems like the observer design pattern

felipeferreira
Автор

Just got this as a 'take-home' interview question. Very similar!

compeng
Автор

Something I wipped up in 5 minutes. This isn't exactly event emitter, but somwhat of the same thing, except a simpler way of understanding it without classes. This is definitely a great interview questions.

Interviewer would have definitely ask something like, implement the pub/sub pattern you see all the time in JS.

const Event = {
events: {},
on: function(eventName, func) {
this.events[eventName] = func
},
fire: function(eventName) {
this.events[eventName]()
}
}

Event.on('event1', function event1() {
console.log('event1') // event1
})

Event.on('event1', function event1() {
console.log('event1 - override') // event1
})

Event.on('event2', function event2() {
console.log('event2') // event2
})

Event.fire('event1') // event1 - override
Event.fire('event2') // event2

hackingthejsinterview
Автор

Excellent video. Implementing this in JS was something I was wondering for some time. Thank you.

guywald
Автор

Thank you Stephen. You just my timer saver... cheers!

Samsul
Автор

I was asked this interview question today and definitely struggled at first. Was able to complete it though!

ambitious_grass
Автор

the " ...rest " just saved my virtual javascript life, great vid, peace

kariboo
Автор

Hi thank for the vid! One thing, the trigger seems not to forward multiple arguments with apply() this way, so I figured someone might try



trigger = (eventName, ...rest) => {
if(this.events[eventName]) {
callback => {
callback.call(null, ...rest);
})
}

}


instead, which relays all arguments passed. Cheers!

kalleneumann
Автор

Two questions here:
1. The trigger function will call *all* callbacks registered to that event with the specified arguments. So it follows that if:

this.events[eventName] = [cb1, cb2, cb3]

and I 'trigger' with trigger ( 'eventName', [arg1, arg2, arg3] ) that this will call cb1, cb2, cb3 thus:

cb1(arg1, arg2, arg3)
cb2(arg1, arg2, arg3)
cb3(arg1, arg2, arg3)

Let's hope all the callbacks take the same arguments....

2. What's the point of the emitter? Can I get some use cases?

xen
Автор

You can avoid the if else statement in the "on" method by dirrectly push the callback on the event array after adding this line of code : (events[eventName] || (events[eventName] = [])).push(...).

nacimhoc
Автор

Why did you chose to execute the callbacks with cb.apply(null, rest) instead of just cb(rest) ? Isn't it preferable that the callback keeps its context, in case it had something like "this.someProp" in its code?

MitchKarajohn
Автор

Why do we need an event emitter class?

HarpreetSingh-jdtu
Автор

Hi, if u call method "trigger" like this
trigger('change', 'vasya');
And early define like this
ee.on('change', (name) => {
console.log('hello ' + name + ' there!');
});
Result will be "hello undefined there!"
Maybe need fix this code:
=> {
cb.apply(rest);
});
to change
=> {
cb.apply(this, rest);
});
Or i dont understand purpose of rest arg?

КонстантинГиль-ря
Автор

/*


The Prototypal approach, in case you needed to pass objects rather than a pointer.

*/
const EventEmitter = function(n){
this.name = n
this.events = {}
return this
}
EventEmitter.prototype.on = function(eventName, callback){
this.events[eventName] ? : this.events[eventName] = callback

}
= function(eventName, ...args){
!(this.events[eventName]) || callback(this.name, this.events, args)

function callback(n, eventList, a){
for (n in eventList) {
(eventList[n]).apply(this, a)
}
}


}
/*
As seen below

*/
let foo = new EventEmitter('foo')
foo.on('foo', (a) => {
console.log(a.handle)
a.crow()
})
foo.trigger('foo', {
handle: 'bar',
crow: () => {
setInterval(() => {
console.error(' { [ [!!!SQUAK!!!!} } }')
}, 500)
}
})
console.log(typeof foo)
console.log(typeof foo.trigger)
console.log(typeof foo.on)
console.log(foo.__proto__)

urbansilhouettemedia