Thursday 17 January 2013

Javascript: It's All a Question of Timing - Part 2

Modularise and Re-Use


In the previous post we explored how system latency can affect timing and how adjustments can be calculated and applied to mitigate this drift.

In its raw form, the JavaScript snippet provides a base for us to create a re-usable, modular library that can be placed into any website with minimal configuration.

First off is to encapsulate the functionality within its own namespace and function.






This keeps the global namespace free from pollution and provides a container for our session timer methods. Notice that the sessionTimer is a self-invoking function.

We'll be applying a Revealing Module pattern approach to the sessionTimer. This is a slight variation on Douglas Crockfords popular Module pattern which allows us to include 'private' variables and functions internally, whilst 'publicly' exposing only those functions that we offer external access to. In this case, we want to define a few variables and default settings.





The settings are comprised of an object literal containing a series of default properties. These are intended to be updated depending on the situation in which they are used - we'll see that a little later. Included in the settings are a series of callback functions which allow the implementing site to react to various events, such as reminding the user that their session is about to expire.

The sessionTimer includes a few private functions which initialise, validate and process the timer. The following snippet illustrates the skeleton of the module. We'll take each function in turn to point out the salient points, beginning with _init.



_init allows the consuming document to specify its own particular settings and pass them into the sessionTimer. These will extend the default settings and ensure that the sessionTimer is initialised appropriately.

_validateTimer simply ensures that the settings' values are within an acceptable tolerance. For example, the sessionTimeout must be greater than 0 and that the checking interval must be greater than 0 and less than the total sessionTimeout. 



If all settings values are valid _control kicks off the sessionTimer by calling _countdown. We need to split the timer into two sections. The first being a countdown to triggering the reminder callback function, the second being the remaining time before the session expires. _control achieves this by calculating the pre-reminder time and calling _countdown. _countdown includes a 'complete' callback and, when triggered _control recalls _countdown passing in the remaining time)




Much of the basis behind _countdown should already be familiar to you as this was the crux of the last post. The differences here being: the inclusion of a _countdownExecuting flag which is used by _stop to determine whether the sessionTimer can be terminated, and that _countdown is a descending timer. Rather than starting at zero and counting up, we're starting at totalms provided and counting down to zero. The function also includes 2 callbacks: tick and complete. 'Tick', if supplied, will trigger each time that _countdown tests whether the countdown has complete. Under default conditions this will be once every second (+/- latency). 'Complete' will trigger when the timer has actually finished / reached zero. 




The _stop function simply stops the timer regardless of the amount of time remaining. If a callback is required, the 'stopped' callback is fired.  




Under the Revealing Module pattern these are all private functions and are accessible outside the sessionTimer function. But, we need to interact with sessionTimer from whichever site is consuming the module. Therefore, we return an object literal of functions that can be considered 'public'. In other words, the outside world can interact with certain functions. In this manner, sessionTimer.init maps internally to _init, sessionTimer.doCountdown maps to control. 




 So, our sessionTimer module is ready and here it is in its entirety.





The Final Furlong


To test and run the sessionTimer module we need only to initiate it with settings specific to the site that will consume it, and set it in motion. To make it more palatable for testing, rather than waiting for the default 20 minutes to elapse before the sessionTimer completes, lets reduce the time to 20 seconds, with a reminder when 8 seconds remain. We'll also supply the various callback functions we want to use. These will simply log the output to the console window.




I like Firebug (Firefox) for throwaway tests like this, so in Firebug execute the sessionTimer module followed by the code above. You should see in the console window that the sessionTime counts down 12 seconds, displays 'reminder', counts down the remaining 8 seconds and finalises with 'complete'.

Alternatively, here's an example web page with the timer intialised and executed automatically. 






See the Javascript Session Timer in action



Written by Dan Hacker, Software Developer, DSCallards

For more information, visit www.dscallards.com.


 

No comments:

Post a Comment