Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 55cf38b

Browse files
committed
added an event loop fundamental
1 parent 24e8567 commit 55cf38b

8 files changed

+175
-0
lines changed

fundamentals/assets/call-stack.png

14.5 KB
Loading

fundamentals/assets/event-loop-1.png

29.7 KB
Loading

fundamentals/assets/event-loop-2.png

20.3 KB
Loading

fundamentals/assets/event-loop-3.png

32 KB
Loading

fundamentals/assets/event-loop-4.png

25.3 KB
Loading

fundamentals/assets/event-loop-5.png

8.34 KB
Loading

fundamentals/assets/sync-async.png

12.1 KB
Loading

fundamentals/event_loop.md

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
# Event Loop
2+
3+
## YouTube Video
4+
5+
This article is a companion to the excellent YouTube video [What the heck is the event loop anyway?](https://www.youtube.com/watch?v=8aGhZQkoFbQ) by Philip Roberts.
6+
7+
[![Event Loop](https://img.youtube.com/vi/8aGhZQkoFbQ/0.jpg)](https://www.youtube.com/watch?v=8aGhZQkoFbQ "Event Loop")
8+
9+
## Introduction
10+
11+
The way of programming when developing JavaScript applications for the browser is sometimes called _Event-Driven Programming_. Once a JavaScript program has been loaded in the browser and has completed its initialization, it is normally waiting for specific "events" to happen. These events can take the form of mouse movements and clicks, keyboard interactions and network-related events (e.g. a response from an `XMLHttpRequest`)*.
12+
13+
In order for a JavaScript program to respond to a specific (type of) event, a programmer needs to add an "event listener" for the event type of interest to the target DOM element or network request object.
14+
15+
Event examples are:
16+
17+
- a `'click'` event from an HTML button element.
18+
- a `'load'` event from an XMLHttpRequest.
19+
20+
A JavaScript program can also set up one or more timers and execute a function when a specific timeout expires. One could consider these to be _software-initiated_ events.
21+
22+
When a event occurs, the browser places an object with information about the event along with the JavaScript function designated to handle the event in an Event Queue. When the JavaScript engine is idle (i.e. when the call stack is empty, see below), it picks up the next event from the Event Queue and invokes the corresponding event handler, passing the event object as a parameter. This mechanism could be depicted by the follow pseudo-code:
23+
24+
```
25+
// Event Loop
26+
while (waiting_for_event) {
27+
execute_event_handler(event)
28+
}
29+
```
30+
31+
32+
\* Note: There are more [Web APIs](https://developer.mozilla.org/en-US/docs/Web/API) available in the browser that could potentially generate events, e.g. the [SpeechSynthesis API](https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesis) and the [MIDIAccess API](https://developer.mozilla.org/en-US/docs/Web/API/MIDIAccess), to name just two.
33+
34+
## Call Stack
35+
36+
In Figure 1 below, when function **A** ① calls function **B** ②, which in turn calls function **C** ③, the JavaScript engine must keep track where function **B** was at the moment that **C** was called, so that it can continue executing **B** when function **C** returns ④ . The same applies to function **A** when function **B** returns ⑤.
37+
38+
For this purpose the JavaScript engine maintains a [call stack](https://developer.mozilla.org/en-US/docs/Glossary/Call_stack) as shown in Figure 1, The call stack is a first-in, first-out data structure. When a function is called it is pushed onto the call stack and when it returns it is popped of the call stack.
39+
40+
![Call Stack](assets/call-stack.png)
41+
42+
Figure 1. Call Stack
43+
44+
## Example Code
45+
46+
We will use the example application below for our discussion of the event loop. The application consist of a simple HTML page with three buttons and an associated JavaScript file. The web page looks like this:
47+
48+
![Syn/Async Demo Page](assets/sync-async.png)
49+
50+
All output resulting from button clicks will be printed in the browser's console.
51+
52+
### index.html
53+
54+
```html
55+
<!DOCTYPE html>
56+
<html>
57+
<head>
58+
<title>Sync/Async Demo</title>
59+
<style>
60+
button {
61+
margin-right: 4px;
62+
}
63+
</style>
64+
</head>
65+
<body>
66+
<div>
67+
<h1>Sync/Async Demo</h1>
68+
<button id="btn-sync">START SYNC TIMER</button>
69+
<button id="btn-async">START ASYNC TIMER</button>
70+
<button id="btn-hello">HELLO</button>
71+
</div>
72+
<script src="app.js"></script>
73+
</body>
74+
</html>
75+
```
76+
77+
### app.js
78+
79+
The JavaScript file `app.js` adds a `'click'` event listener for each of the three buttons. Rather than using anonymous functions for the event handlers, all functions are given a name so that these names show up in the call stack should we run this code in the Chrome debugger.
80+
81+
```js
82+
'use strict';
83+
'use strict';
84+
{
85+
function synTimeout(delay) {
86+
const stopTime = Date.now() + delay;
87+
while (Date.now() < stopTime);
88+
}
89+
90+
function addSyncOnClickListener() {
91+
document
92+
.getElementById('btn-sync')
93+
.addEventListener('click', function onSyncClick() {
94+
console.log('start sync timer');
95+
synTimeout(5000);
96+
console.log('stop sync timer');
97+
});
98+
}
99+
100+
function addAsyncOnClickListener() {
101+
document
102+
.getElementById('btn-async')
103+
.addEventListener('click', function onAsyncClick() {
104+
console.log('start async timer');
105+
setTimeout(function onTimeout() {
106+
console.log('stop async timer');
107+
}, 5000);
108+
});
109+
}
110+
111+
function addHelloOnClickListener() {
112+
document
113+
.getElementById('btn-hello')
114+
.addEventListener('click', function onHelloClick() {
115+
console.log('Hello, world!');
116+
});
117+
}
118+
119+
window.onload = () => {
120+
addSyncOnClickListener();
121+
addAsyncOnClickListener();
122+
addHelloOnClickListener();
123+
};
124+
}
125+
```
126+
127+
### Synchronous, blocking code
128+
129+
In Figure 2.1 below, when the **START SYNC TIMER** button is clicked ①, a `click` event with its `onSyncClick` event handler is placed in the Event Queue and, because the call stack is empty, is immediately executed. The `onSyncClick` function calls the `synTimeout` function, passing the desired time delay in milliseconds in the `delay` parameter. The call stack at this point in time is depicted in ②.
130+
131+
The `synTimeout` function keeps racing around in a tight `while` loop, in each loop iteration calling `Date.now()` to check whether the specified delay has already been reached. While the JavaScript engine is busy executing this `while` loop, it cannot run any other code. In particular, it cannot pick up events from the Event Queue, for instance click events from the **HELLO** button, while the loop is executing ③. The `onHelloClick` event handler awaits execution in the Event Queue (with the browser appearing to be unresponsive) until the `synTimeout` function completes, and with it, the `onSyncClick` function (Figure 2.2, ④).
132+
133+
![Event Loop 1](assets/event-loop-1.png)
134+
135+
Figure 2.1 The Event Loop - blocking code.
136+
137+
At this point the call stack becomes empty, and the event loop can pick up `onHelloClick` from the Event Queue and execute it ⑤. In the browser this is experienced as a delayed, sluggish response to the click on the **HELLO** button.
138+
139+
Finally, when the `onHelloClick` event handler has finished execution, the call stack becomes empty again ⑥, and the event loop awaits further, future events.
140+
141+
**In conclusion:** Synchronous, blocking code, such as implemented by
142+
the `synTimeout` function is to be avoided as it makes the application appear to be unresponsive.
143+
144+
![Event Loop 2](assets/event-loop-2.png)
145+
146+
Figure 2.2 The Event Loop - blocking code - continued.
147+
148+
## Asynchronous, non-blocking code
149+
150+
In contrast, in Figure 3.1, when we click the **START ASYNC TIMER** button ①, the `onAsyncClick` event handler is placed and the Event Queue and, because the call stack is empty, is immediately executed ②. It in turn calls the `setTimeout` function provided by the browser (**not** the JavaScript engine!). This starts a timer internal to the browser ③. Once the timer has been set up the `setTimeout` function returns and subsequently the `onAsyncClick` event handler exits.
151+
152+
Suppose that one second later we click the **HELLO** button ④. This causes the `onHelloClick` event handler to be placed in the Event Queue. Because the call stack is empty the `onHelloClick` event handler is immediately executed ⑤ and subsequently exits.
153+
154+
![Event Loop 3](assets/event-loop-3.png)
155+
156+
Figure 3.1 The Event Loop - non-blocking code.
157+
158+
159+
When some time later the timer set up in step 3 expires, the `onTimeout` callback is placed in the event queue ⑥. Again, because the call stack is empty at that point in time it is immediately executed ⑦.
160+
161+
![Event Loop 4](assets/event-loop-4.png)
162+
163+
Figure 3.2 The Event Loop - non-blocking code - continued.
164+
165+
Subsequently it exits, leaving the call stack empty again ⑧, ready to take on new events from the event loop whenever they occur.
166+
167+
![Event Loop 5](assets/event-loop-5.png)
168+
169+
Figure 3.3 The Event Loop - non-blocking code - continued.
170+
171+
**In conclusion:** Asynchronous, non-blocking code is to be preferred at all times to ensure that the application maintains its responsiveness.
172+
173+
## More Information
174+
175+
Mozilla Developer Network: [Concurrency model and Event Loop](https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop)

0 commit comments

Comments
 (0)