Does the dispatching of an event queue a future task, or is the event dispatched straight away? And when are event listeners executed? Eventually or straight away? This lesson will show you how dispatching an event occurs synchronously and all event listeners on the event path are also executed synchronously.
Instructor: [0:00] Dispatching an event is synchronous, and all event listeners on the event path will be executed immediately within the current call stack. Here I'm adding a click event listener to the button which is going to log out listener. After this button.dispatch call I'm going to log out after event.
[0:20] If I come over here to the browser and I refresh the page, I'll see that this console.log to listener which was executed when this button.dispatch event call happened was logged first and then after event was logged.
[0:34] The important call out here is that dispatchEvent is not queuing up any kind of asynchronous work. This is all happening synchronously.
[0:42] We've seen previously that dispatchEvent will return a Boolean, which represents whether the event was allowed or cancelled. The only way that dispatchEvent would be able to have this behavior is if dispatchEvent was synchronous. If it was asynchronous, we would get back something like a promise or some other future value here.
[1:02] It's totally possible to dispatch an event while another event is dispatching. Here, I am adding an event listener to button for the event A, and this function onA(), it's going to log out "onA start," and then it's going to dispatch a new event called B, and then it's going to log "onA finish."
[1:23] I'm also adding another event listener for the event B, with a function onB(), which is going to log out "B." Here, I'm creating a new event with the type A, and then I'm dispatching that event on the button. Let's come over to the browser and see what happens.
[1:40] Let's trace this through. We're creating a new event. It's dispatching. OK, this is getting picked up by this event listener in onA function. We're seeing "onA start," and then we're calling dispatchEvent with a new event, B.
[1:55] That's then getting picked up by this event listener, which was listening for the B event, and inside the onB function, it's logging out "B." That's all finished. It's going to exit out here and log out "onA finish."
[2:09] This behavior can cause performance problems in applications if you are doing some heavy processing in your event listeners, as each dispatched event is increasing the time that it takes for the current task to complete, so it's blocking other things from happening.
[2:25] If you do need to dispatch an event in response to another event, you might consider scheduling some future work -- in this case, I'm using setTimeout to schedule a future task -- to dispatch that second event. This gives the browser a chance to do other things, such as rendering, before having to process this event.
[2:44] Keep in mind this is a change in behavior. First, we're logging out "onA start," and then we're using setTimeout to schedule some future work to dispatch the second event. Then it's going to log out "onA finish" straight away. We see "onA start on a finish." Then, when this task is executed by the browser, we'll see "B" logged out.
[3:04] Because dispatching events is synchronous, you do need to be careful that you don't create an infinite loop. Here in my A event listener, I'm going to dispatch a new B event. Inside of my B event listener, I'm going to dispatch a new A event. I'm going to dispatch a new A event against the button to kick it all off.
[3:24] Let's see what happens when we run this. Oh my gosh. Maximum call stack size exceeded. Well, that's good. I was expecting the browser might crash. This is probably a little bit nicer. Our original event is dispatched with dispatchEvent synchronously, which is then causing more and more synchronous dispatching of events to happen.
[3:43] All of these synchronous calls are increasing the size of the call stack of our original dispatchEvent call until the browser steps in and says, "We're done."