|
| 1 | +# JavaScript Runtime Environment (JRE) |
| 2 | + |
| 3 | +JavaScript engine doesn’t run in isolation. It runs inside an environment called JavaScript Runtime Environment along with many other components. JRE is responsible for making JavaScript asynchronous. It is the reason JavaScript is able to add event listeners and make HTTP requests asynchronously. |
| 4 | + |
| 5 | +JRE is just like a container which consists of the following components: |
| 6 | + |
| 7 | +1. JS Engine |
| 8 | +2. Web API |
| 9 | +3. Callback Queue or message queue |
| 10 | +4. Event Table |
| 11 | +5. Event loop |
| 12 | + |
| 13 | + |
| 14 | + |
| 15 | +## Web API |
| 16 | + |
| 17 | +Web APIs are not part of the JS engine but they are part of the JavaScript Runtime Environment which is provided by the browser. JavaScript just provides us with a mechanism to access these API’s. |
| 18 | + |
| 19 | +When JavaScript engine finds any Web API method, it sends that method to an event table, where it waits till an event occurs. |
| 20 | + |
| 21 | +In the case of AJAX calls, the JS engine will send the AJAX calls to the event table and will continue the execution of code after the Ajax call. AJAX call will wait in the event table until the response from the AJAX call is returned. |
| 22 | + |
| 23 | +In case of timer function like setTimeout, it waits until the timer count becomes zero. |
| 24 | + |
| 25 | +## Event Table |
| 26 | + |
| 27 | +It is a table data structure to store the asynchronous methods which need to be executed when some event occurs(timeout, click, mouse move). |
| 28 | + |
| 29 | +Event Table does not execute functions and does not add them to the call stack on it’s own. It’s sole purpose is to keep track of events and send them to the Event Queue. |
| 30 | + |
| 31 | +## Callback Queue or Message Queue or Event Queue |
| 32 | + |
| 33 | +These queues follows First In First Out principle (item to be inserted first in the queue will be removed from the queue first). It stores the correct order in which the functions should be executed. |
| 34 | + |
| 35 | +It stores all the messages which are moved from the event table to the event queue. Each message has an associated function. |
| 36 | + |
| 37 | +It receives the function calls from the Event Table, but it needs to somehow send them to the Call Stack? This is where the Event Loop comes in. |
| 38 | + |
| 39 | +## Event Loop |
| 40 | + |
| 41 | +Methods are executed neither in the event table nor in the event queue. They are executed by the JavaScript engine, only if it is present in the ECS. |
| 42 | + |
| 43 | +So, for the execution of any method, engine needs to move that method from the callback queue to the execution context stack. This is what the event loop does! |
| 44 | + |
| 45 | +Event loop continuously checks if the execution context stack is empty and if there are any messages in the event queue. |
| 46 | + |
| 47 | +**It will move the method from the callback queue to ECS only when the execution context stack is empty.** |
| 48 | + |
| 49 | +```javascript |
| 50 | +function printStatement() { |
| 51 | + console.log('I should be printed after timeout'); |
| 52 | +} |
| 53 | + |
| 54 | +setTimeout(printStatement, 0); |
| 55 | + |
| 56 | +console.log('I will be executed first'); |
| 57 | +``` |
| 58 | + |
| 59 | +Some people think that because set timeout is called with 0 (zero) it should run immediately. In fact in this specific example you will see “second” printed out before “first”. JavaScript sees the setTimeout and says “Well, I should add this to my Event Table and continue executing”. It will then go through the Event Table, Event Queue and wait for the Event Loop to tick in order to run. |
| 60 | + |
| 61 | +```javascript |
| 62 | +var log = console.log; |
| 63 | + |
| 64 | +log('Inside global execution context'); |
| 65 | + |
| 66 | +function functionOne() { |
| 67 | + log('Inside function one'); |
| 68 | + |
| 69 | + function setTimeoutFunction() { |
| 70 | + log('Inside setTimeoutFunction: I will be executed atleast after 1 sec'); |
| 71 | + } |
| 72 | + |
| 73 | + setTimeout(setTimeoutFunction, 1000); |
| 74 | + |
| 75 | + for (var i = 0; i < 100000000; i++) { |
| 76 | + // Blocking code. This makes the for loop to execute for more than 1 second |
| 77 | + // Still setTimeoutFunction is not executed. It gets executed only after |
| 78 | + // last statement of the code |
| 79 | + } |
| 80 | + |
| 81 | + log('Exiting functionOne'); |
| 82 | +} |
| 83 | + |
| 84 | +functionOne(); |
| 85 | + |
| 86 | +log('Exiting global execution context'); |
| 87 | +``` |
| 88 | + |
| 89 | + |
| 90 | + |
| 91 | +If the execution context stack is not empty, the event loop will not move the message from the callback queue to the execution context stack. |
| 92 | + |
| 93 | +**Thus, the time passed to `setTimeout` function does not guarantee its execution after the elapse of that time, but it is the minimum time after which setTimeout callback function will be executed.** |
| 94 | + |
| 95 | +**From the above example, we can understand the following things** |
| 96 | + |
| 97 | +1. JavaScript is single thread i.e. at any instant of time it can execute only a single piece of code. |
| 98 | +2. JS engine executes the function which is at the top of the stack |
| 99 | +3. Asynchronous jobs like waiting for the setTimeout callback function to execute is not done by the JavaScript engine itself. It is done by the JavaScript run time environment |
0 commit comments