JavaScript: The Event Loop

JavaScript is event based, meaning everything that happens within a browser window/tab is the result of an event occurring and code responding to that event. There are hundreds of potential events that may need to be responded to throughout the life-cycle of an HTML page.

An important concept to understand, when it comes to JavaScript and the browser, is the event loop, the primary driver of this event based system. The event loop is controlled and managed by the browser which keeps the loop running and dispatches all events as they occur. Due to this, developers are free to focus 100% of their energy on identifying the events they are interested in and writing logic to respond accordingly to those events. This code that is invoked in response to an event is called an ‘event handler’ or ‘listener’.

One of the most complex parts of JavaScript programming is the fact that events are fired unpredictably and in an unpredictable order. This means JS code has to be written in an asynchronous manner with each listener having the ability to be executed independently of all others.

Unlike a lot of other languages out there, the JavaScript event loop is ‘non-blocking’ meaning that JavaScript does not allow the event loop to be monopolized by any single function. This includes I/O (input/output) events, instead of waiting for a file read to complete or a database call to return before moving on, JavaScript requires a listener to be provided and assigns that listener to the I/O return event and it moves on. Ultimately what this does is keep the browser window responsive and usable while long running tasks are taken care of asynchronously. This is a huge advantage being that the browser window is the user interface, which should remain responsive at all times.

Reference: Mozilla Developer Event Loop

To get an idea, here are just some of the most common events that front-end developers deal with on a daily basis, of course there are many more that are just as important as these:

Window Events

  • onload: fires after the page finished loading
  • onerror: fires when an error occurs
  • onresize: fires when the browser window is resized
  • onunload: fires when the page is unloaded or browser window closes

Keyboard Events

  • onkeydown: fires when the user presses a key down and holds it down
  • onkeypress: fires when the user presses a key down and then releases it
  • onkeyup: fires when the user releases the key

Mouse Events

  • onclick: fires when the user clicks on an HTML element
  • ondblclick: fires when the user double clicks on an HTML element
  • ondrag: fires when the user drags an HTML element
  • onmouseover: fires when a user hovers the mouse cursor over an HTML element
  • onmousemove: fires when a user moves the mouse cursor over an HTML element

Reference: Mozilla Developer Web Events

JavaScript: Exception Handling

Exception handling in JavaScript is extremely similar to that in C# or Java. Js utilizes the familiar try-catch blocks to capture exceptions and handle them. You simply wrap code that might throw an exception in the try and then provide a catch to handle the captured exceptions.

Unlike C# and Java, JavaScript does not allow multiple catch blocks nor does it handle capturing exceptions based on specificity. For this you must implement your own code by checking the exception name or using reflection methods to identify the exception types you are after. This is a little cumbersome but doable.

'use strict';

// Exception Handling
//  1. Use 'throw' to create and throw an Exception
//  2. Use the 'name' property to give the Exception an identifiable name
//  3. Use the 'message' property to give the Exception a meaningful message for the user
//  4. Standard Try-Catch as we are used to in Java and C#
//  5. Place code which might create an error in the 'try' block
//  6. Place rescue code in the 'catch' block
//  7. 'try' blocks can only have one 'catch' and one only
//  8. Must check Exception name in order to handle more than one type of Exception at a time

try{
    // Code that can cause an error during execution

    // Code actually throwing an Exception
    throw {
        name: "CustomErrorType",
        message: "I just threw an error at you."
    }
}catch(error){
    if(error.name === "SomeOtherError"){
        // Do something here
    }

    if(error.name === "CustomErrorType"){
        // Code to rescue processing from the error
        console.log("Captured and error: " + error.name);
        console.log("Its message is: " + error.message);
    }
}

JavaScript: Cascading Methods (Method Chaining)

One extremely useful programming pattern that can be implemented in JavaScript is that of ‘cascading methods’ also known as ‘method chaining’. Method chaining is accomplished in JS by simply returning the object that was just operated on as the result of the method call. By doing this, a developer can call a method and then instantly call another method on the same object without referencing the object or capturing the result of the previous method call.

This is possible due to the fact that the result of a method is returned directly after the method call itself and is therefore used as the object of interest for the following (chained) method call (see example code below).

'use strict';

// Cascading/Chaining Methods
//  1. Return 'this' instead of 'undefined' at the end of your Methods
//  2. This allows the focused Object to be returned and additional Methods to be called on it

var person = {
    first_name: 'First name not provided',
    middle_initial: 'initial not provided',
    last_name: 'Last name not provided',
    age: 'Age not provided',

    change_first_name: function(new_name){
        this.first_name = new_name;
        return this; // Return the current object
    },

    change_last_name: function(new_name){
        this.last_name = new_name;
        return this; // Return the current object
    },

    change_middle_initial: function(new_initial){
        this.middle_initial = new_initial;
        return this; // Return the current object
    }
};

// Call each of the Object's methods one right after the other
person.change_first_name('Tim').change_middle_initial('').change_last_name('Clark');

console.log('First Name: ' + person.first_name);
console.log('Middle Initial: ' + person.middle_initial);
console.log('Last Name: ' + person.last_name);