Showing posts with label JAVASCRIPT. Show all posts
Showing posts with label JAVASCRIPT. Show all posts

Thursday, May 12, 2016

Display Loading Indicator with Interceptors in Angular

Most Single Page Applications (SPA) written in Angular, utilize a plethora of asynchronous service calls in the background, some completing instantly and some taking a very long duration just because your ISP provides blazing speeds. Nevertheless, during such situation, it is essential that you display a loading indicator that suggests something like "Loading.." or "Please wait, your connection sucks!".

If your application contains a magnitude of $http service calls that you could hardly remember yourself, modifying each of them to display a loading indicator and hide it before and after each request will kill your time and ultimately you. Just imaging maintaining it! Is there a better way to enable this feature?

I feel your pain, hence this blog is about to detail a mechanism of how you can conveniently incorporate a loading indicator using a custom interceptor that plugs in to the AnguarlJS $httpProvider. To demonstrate this lets create a simple application where upon the user clicking a button we will query a backend service while displaying a loading indicator throughout the period of the HTTP request roundtrip.

Folder Structure

I like segregating an application into specific files and modules merely for maintainability. Before we dive in to the nitty-gritty details, lets observe the Angular application folder structure shown below that I opted to, which by no means are you restricted or limited to,

The pink square depicts the shared module, where I will have shared controllers, services, etc. indexController.js will be a controller that will be used to perform a simple http request. The utilityService.js contains a simple utility function to generate a unique ID and the httpInterceptorService.js will be the interceptor that is used to show/hide the loading indicator for each http request made via Angular.

The red square depicts the application where I have a module.js and rootController.js defined. The module.js at this level is responsible of injecting all the other modules that the application is dependent on (e.g. shared/module.js).

Below is the markup index.html page created as part of this solution, which details the loading of each file and the bootstrapping of the application,

<html>
<head>
    <title>Display Loading Indicator with Interceptors in AngularJS</title>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.5/angular.min.js"></script>
    <script type="text/javascript" src="https://code.jquery.com/jquery-2.2.3.min.js"></script>
    <script type="text/javascript" src="app/module.js"></script>
    <script type="text/javascript" src="app/rootController.js"></script>
    <script type="text/javascript" src="app/shared/module.js"></script>
    <script type="text/javascript" src="app/shared/services/utilityService.js"></script>
    <script type="text/javascript" src="app/shared/services/httpInterceptorService.js"></script>
    <script type="text/javascript" src="app/shared/controllers/indexController.js"></script>
    <link rel="stylesheet" href="Styles/styles.css" />
</head>
<body ng-app="app" ng-controller="app.RootController">
    <div ng-controller="shared.IndexController">
        <button ng-click="getData()">Get Data</button>
        <div>
            <ul ng-repeat="contact in contacts">
                <li>{{contact}}</li>
            </ul>
        </div>
    </div>
</body>
</html>

Notice the app.RootController at the top most level, and the shared.IndexController at a child level. This will enable the addition of common functionality to the root controller that can be invoked throughout the applications life cycle. Lets see how we could add the show/hide ability of the loading indicator to the root controller below.

Toggling the Loading Indicator

The rootController.js is responsible as functioning as the top-most controller for the entire application and will be the controller the application is bootstraped with, and is typically where its most suitable to add all application wide functionality such as the show/hide functionality of the loading indicator we indent to enable,

angular.module('app')
    .controller('app.RootController', ['$rootScope', function ($rootScope) {

        // Collection to maintain load order.
        var _loadList = {};

        // Display the loading message.
        $rootScope.showLoading = function (id, message) {

            if (_loadList != null && _loadList[id] == null) {
                var data = { id: id, message: message }; 7
                _loadList[id] = data;
            }

            var loadElement = $('div[data-load]');
            if (loadElement.length == 0) {
                $('body').append('<div data-load class="preloader"><img src="http://www.downgraf.com/wp-content/uploads/2014/09/01-progress.gif" /><p data-load-message>' + message + '</p></div>');
            } else {
                loadElement.find('p[data-load-message]').text(message);
            }
        };

        // Hide the loading message.
        $rootScope.hideLoading = function (id) {
            if (_loadList != null && _loadList[id] != null) {
                delete _loadList[id];
            }

            if (Object.keys(_loadList).length != 0) {
                var data = _loadList[Object.keys(_loadList)[Object.keys(_loadList).length - 1]];
                if (data.id != null) {
                    _showLoading(data.id, data.message);
                    return;
                }
            }

            var loadElement = $('div[data-load]');
            loadElement.remove();
        };
    }]);

The code is fairly simple. There are two functions bound to the $rootScope which is showLoading(id, message) and hideLoading(id).  The showLoading(id, message) function is responsible of queuing the message based on the ID and then displaying a animated GIF image that is dynamically added to the DOM using JQuery. The hideLoading(id) function is responsible to removing the ID from the queue and hiding the loading indicator from the DOM. If there are other loading messages queued in the _loadList array, the hideLoading(id) function is responsible of displaying the next immediate loading message.

Having code to show/hide the loading indicator is all good, but we need to enable the mechanism of showing/hiding or invoking the showLoading(id, message)/hideLoading(id) functions accordingly for each $http service request invocation. Lets see on how to enable that using interceptors in Angular next.

Configuring the HTTP Interceptor

We all know what $http in Angular is. The $http is a service in Angular that supports the communication with a backend server via HTTP. Hence in order to add a loading indicator we need the ability to pre/post process each of the requests executed via the $http service. The $httpProvider is how Angular enables this ability, where it contains an array named interceptors. An interceptor in the context of $httpProvider is simply an object that will contain for important methods, which in-fact are request(...), requestError(...), response(...) and responseError(...) that will be triggered for each request made via $http service.

Simple enough! All we need is a mechanism to trigger a way to display a loading message when the request(...) function is triggered and hide the loading message when requestError(...), response(...) and responseError(...) is triggered. Lets see the code of the custom interceptor below,

angular.module('shared')
    .factory('shared.httpInterceptorService', ['$rootScope', '$q', 'shared.utilityService', function ($rootScope, $q, utilityService) {

        // Shows the loading.
        var _showLoading = function (id, message) {
            $rootScope.showLoading(id, message);
        };

        // Hides the loading.
        var _hideLoading = function (id) {
            $rootScope.hideLoading(id);
        };

        return {
            // On request success
            request: function (config) {

                // Inject unique ID to config and and show loading. Show loading only if backgroundLoad property is not set or set to false.
                if (config != null) {
                    config.id = utilityService.scriptHelper.getUniqueId();
                    _showLoading(config.id, config.loadMessage != null ? config.loadMessage : 'Loading...');
                }

                // Return the config or wrap it in a promise if blank.
                return $q.when(config);
            },

            // On request failure
            requestError: function (rejection) {

                // Hide loading triggered against the unique ID.
                if (rejection != null && rejection.config != null) {
                    _hideLoading(rejection.config.id);
                }

                // Return the promise rejection.
                return $q.reject(rejection);
            },

            // On response success
            response: function (response) {

                // Get unique id from config and hide loading. Hide loading only if backgroundLoad property is not set or set to false.
                var config = response.config;
                if (config != null) {
                    _hideLoading(config.id);
                }

                // Return the response or promise.
                return $q.when(response);
            },

            // On response failure
            responseError: function (rejection) {

                // Hide loading triggered against the unique ID.
                if (rejection != null && rejection.config != null) {
                    _hideLoading(rejection.config.id);
                }

                // Return the promise rejection.
                return $q.reject(rejection);
            }
        };
    }]);

There are a couple of things going on here. First off, lets understand the four important methods of the interceptor,

  • request(...) function: This function is called before the request is sent over to the backend. The function is passed with a configuration object and you are free to modify the config object as required and this config object will be passed to each of the other three functions. Likewise I am adding a unique ID generated via the utilityService.js to the config object, which will then be passed to the _showLoading(id, message) function and get queued. You are further required to return a valid configuration or promise or the request will be terminated/rejected.

  • response(...) function: This function is called as soon as a response is received from the backend. As of this point we retrieve the unique ID from the config object and call the _hideLoading(id) function. You are further required to return a valid configuration or promise or the request will be terminated/rejected.

  • requestError(...) function: The current interceptor is not the only interceptor, and there can be interceptors chained together. During certain situations a request can fail due to other interceptors throwing errors, or for other network or backend related issues. in this case as well we retrieve the unique ID from the config object and call the _hideLoading(id) function. You are further required to return a valid configuration or promise or the request will be terminated/rejected.

  • responseError(...) function: At certain tims there are situations where interceptors in the chan fail, or there can be situation where the backend failed to provide a successful response. In either case we retrieve the unique ID from the config object and call the _hideLoading(id) function. You are further required to return a valid configuration or promise or the request will be terminated/rejected.

You may have noticed the term promise quite a few times. Promise is a JS based pattern for differed execution/asynchronous programming. Please refer the $q documentation to gain more understanding on the promises in the context of Angular.

Summary

Provided all goes well, you should see and output similar to the following for each $http invocation in you application,

Provide you are unable to get things working, download the sample application from below and try it out.

Happy Coding!

Thursday, June 6, 2013

SignalR – Real-time application development

Introduction

Real-time applications for the web are none other than usual client-server applications with one distinct feature, that being they accomplish functionality with very little (near real-time) or zero latency (real-time). There have been a number of traditional approaches in the past that were employed in order to achieve such functionality suing a variety of methodologies. One such mechanism is Comet, which is an umbrella term that provides a variety of models/solutions in order to achieve real-time application development over HTTP (Hyper Text Transfer Protocol) (e.g. Streaming, Hidden iframe, Ajax with long polling, etc.).
 
There are a number of third-party frameworks available today, until recent Microsoft had no streamlined mechanism that enabled a straightforward approach in the implementation of real-time applications. Although frameworks such as WCF (Windows Communication Foundation) did support a similar functionality using a couple of bindings, wsDualHttpBinding for web services and httpPollingDuplex Silverlight based applications, they had limited features in terms of scale and functionality. Apart from that, you were pretty much on your own if you needed to develop an application that required real-time functionally using ASP.NET.
 

Limitations of a typical Request-Response oriented Application

HTTP functions on the request-response principle, where the client makes a request and the server responds. This is the case with any application web application that runs on HTTP. This is illustrated below,
 
 Request response
 
This mechanism does not provide us the means to achieve real-time data transfer, mainly due to the reason that the server is not able to provide any updated unless the client specifically requests for it. One typical way that developers utilized to overcome this limitation is by performing periodic polling, where the client keeps on requesting until the server has an update to provide the client with as illustrated below,
 
 
Although the above mechanism tries to eliminate the afore mentioned drawback of implementing real-time web application using HTTP, it still could not be considered as an appropriate solution.
 

ASP.NET SignalR

ASP.NET SignalR is a framework maintained and developed by Microsoft that provides just the right functionality that helps you achieve seamless development of real-time applications using ASP.NET. SignalR incorporates a variety of mechanisms/modes that help handle failover during failure to negotiate on a specific transport mechanism to perform real-time message exchange. The framework also supports a straight forward development approach by exposing an API over the core functionality enabling you to develop applications in a breeze. SignalR is written so that it is scalable as you application grows and perform well even when the application requires handling many concurrent users at a given time.
 
SignalR provided four mechanisms in order to overcome the limitations associated with the traditional HTTP request-response principal during development of real-time web applications. Two of these mechanisms use new features introduced with HTML5 version, which are WS (Web-Sockets) and SSE (Server-Sent-Events). As of writing these two features are currently as draft within the HTML5 specification, although most modern browsers do support these features and will continue to evolve in future. The other two mechanisms SignalR supports are Forever Frame and Long Polling.
 
Upon SignalR framework being integrated to an application the framework will choose one of the best mechanisms based on the browser/server capabilities and agree on the transport negotiate accordingly. From a developer standpoint all that you will do is code against the high-level API that will encapsulate the negotiation of which mechanism to use. The key point to understand is that the code you write using framework is the “SAME” regardless of which transport mode you use. Listed below is more information on each of the transport modes supported by SignalR.
 

WS (Web-Sockets)

WS is a new protocol (i.e. ws:// or wss://) introduced with HTML5 and is the most appropriate technology for building real-time applications. That is due to the fact that WS enables creation of a Full-Duplex Bidirectional channel over HTTP enabling the client or the server to send messages independently.
 
 
As illustrated above upon the client creating a WS connection between the servers both server and client will utilize a full-duplex channel over HTTP enabling the server to send event data and the client to send data via the same connection. WS is the preferred over the other options below, due to the fact that it is very preformant and less resource intensive in its essence.
 
This feature is a new addition to HTML and hence requires alterations on an architectural level. Hence it requires that WS be supported in the web server, client browser and all intermediate associates (e.g. proxies, firewalls and server, client, public network infrastructures).In order to enable WS with ASP.NET the prerequisites are that the application must be running on ASP.NET 4.5 or MVC 4, IIS8 (or IIS8 express within Windows Server 2012) with a WS compatible browser.
 

SSE (Server-Sent-Events)

SSE is again an HTML5 feature which enables event based streaming over HTTP. On the contrary to WS, SSE is a mere addition to the JS API (i.e. EventSource object), hence requiring no major change architecturally. This feature is supported by most browsers available today.
 
 
SSE is not a duplex connection like WS. As illustrated above it is a one way connection so that the server can send updates to the client. SSE is achieved by the client creating an EventSource object via JS and the server flushing event data as and when there is an update triggered without terminating the stream. Should there be any client update to be sent, this will be sent via a separate request to the server and not using the event source created between the server and the client which can be considered somewhat of a limitation.
 

Forever Frame

This mechanism is a way of using existing HTML functionality to utilize real-time functionality. It is achieved by creating a hidden iframe within the client to connect to the server and use scriptlets sent by the server to trigger update within the client page. The functionality is similar to using SSE, although in this case this technique uses available HTML iframe element in order to achieve the similar functionality.
 
 
As illustrated the scirptlets sent by the server are appended to the iframe body and a mechanism of reading the script and executing it will be handled by the client accordingly.
 

Long Polling

This is technique that works across all browsers. Long polling is a last resort used by SignalR when determining a transport mechanism to use. Long polling functions in a manner that it sends Ajax based requests to the server where the server holds on to the request for a definite period of time and terminates the request with an empty response. However in cases where there is an server event that needs to be sent across to the client the server immediately sends the response for the client to use, and the client initiates another request to server that will again listen to any server update available.
 
 
Long Polling is considered more resource intensive compared to the other methods supported by SignalR. This is mainly due to the continuous connection initiated and terminated between he server and the client.
 

SignalR transport precedence

The above four mechanisms are supported by the SignalR framework and it will utilize the most effective based on the capabilities of the client/server and fallback to another mechanism if failed. The order of fallback within the framework is as follows,
1. Web-Sockets: SignalR will try to determine if the server/client or intermediate channels support Web-Sockets and use it.
2. Server-Sent-Events: Falls back from Web-Sockets if the browser supports Server-Sent-Events.
3. Forever Frame: Falls back from Server-Sent-Events if the browser supports this mechanism.
4. Long-Polling: Is the fail safe mechanism utilized by SignalR in cases where none of the above technologies are supported.
 

Summary

SignalR is a framework maintained by Microsoft and provides features and means of how real-time messaging can be achieve between the client and the server over HTTP. SignalR supports four main mechanisms of transport (i.e. Web-Sockets, Server-Sent-Events, Forever Frame and Long Polling). SignalR also provides and intuitive API and exposes multiple programing models that aids ease of development which will be looked at in a future post and demos.

Sunday, July 15, 2012

Tree View Checkbox JQuery Selection

Adding JQuery Hierachical Selection

Asp.Net TreeView control is a useful control when hierarchical data representation is required in an .aspx page. The Treeview control inherently supports enabling of checkboxes for node level selection. I came a across a problem where I needed a solution for the following, 1. Checking a node should cause all its child nodes to be selected. 2. Checking a node should cause all its parent nodes to be selected. In order to this it was just a matter of adding a few lines of JQuery to the aspx page. Thanks to JQuery’s wealth of convenient methods it resulted in a few lines. Listed below is the javascript code for your reference.

You can download the DEMO solution from here.

About Me

I am a software developer with over 7+ years of experience, particularly interested in distributed enterprise application development where my focus is on development with the usage of .Net, Java and any other technology that fascinate me.