I will show you how to take your Ajax
applications to the next level by using design patterns in your code to
help you optimize and build scalable applications that can be easily
updated with future features.
Design patterns help solve common programming problems. For
instance, the Singleton pattern solves the problem of having to
instantiate multiple instances of an object throughout an application by
simply giving our application one reference that never changes. This is
how the Singleton pattern specifically solves a common programming
problem.
Objects that utilize the Singleton pattern provide a consistent
reference for other objects in the web application. A Singleton object
is one that cannot be instantiated more than once. This means that
multiple instances of the object cannot be created. You might be asking
why you would want an object that cannot be instantiated by other
objects in a web application. we will explain why, help you understand
how this pattern is useful, and show you how to use this pattern in your
Ajax applications by creating an object that handles all of your Ajax
updates.
An Overview of the Singleton Pattern
Imagine having a large-scale Ajax application with dozens of objects. In this application, you would like to add an object that handles all your Ajax updates. We will call this object the AjaxUpdater.
All the objects in your web application will communicate through this
object if they need to make an XHR at any time. Not only will this
object handle all the requests, it will also handle delegating the
responses to specified callback methods. In other words, when the
response has been received, the AjaxUpdater will notify the requesting object if a callback method was specified during the request. This situation
would require the use of the Singleton pattern because we would need a
consistent object reference for the dozens of objects in our application
that might be making XHRs. This pattern will also help separate this
important functionality into a specific object for more flexibility, and
help keep the web application decoupled for easy updates and future
additions to the code. It might seem odd at first to separate your code
into so many different objects, but as your application grows it will
keep your code extremely easy to update and save you a lot of time in
the long run.
Creating an Object Using the Singleton Pattern
Creating a JavaScript object with the Singleton pattern is so
simple and intuitive. To instantiate a Singleton object, simply write
the following line of code:
AjaxUpdater = {};
Instantiating the object is truly this simple and, as you can
see, it only allows us to create the one reference to the object within
the object itself. This object will then be used throughout the rest of
the web application for constant reference. Now that we have our object
instantiated, all we have to do is call it by name from anywhere in the
application to access its properties and methods.
Creating properties and methods in a Singleton object is just as
simple as instantiating the object. Write the name of the object,
followed by the name of the method, and then point it to a new function,
with any associated parameters if necessary. Take a look at the example
of the initialize method in the below code snippet.
1.Creating a Method in a Singleton Object (AjaxUpdater.js
)AjaxUpdater.initialize = function()
{
AjaxUpdater.isUpdating = false;
}
AjaxUpdater.initialize();
The initialize method needs to be invoked after it is created in order to initialize the
object before we can use the rest of its methods. It also prevents JavaScript from throwing an error because the method will not have existed at this point.
This method initializes the AjaxUpdater and, although it does not accept any parameters, it is used to set all the
local properties for the object. If this object is not initialized, the properties of the object will not be properly instantiated when we try to
access their values, resulting in unexpected behaviors. Creating a property in a Singleton object is as simple as typing the name of the object, followed by
the property you want to create.
AjaxUpdater.isUpdating = false;
In the preceding example, we are creating a Boolean property named isUpdating. This property is set to false by default because the object is not currently active, which means that it is not currently updating any requests or waiting for any responses. The isUpdating Boolean will be used to determine whether the object is currently updating a request or waiting for a response from the Ajax engine. This property will be extremely useful when we have an application with numerous requests because we might need to decide whether to make a new request based on its value, or we might want to check it if a user is trying to exit the page while a request is in transit to warn him of any potential data loss. There are many other uses for this Boolean value, as we will discover when our application grows larger and has numerous active requests. After we have our object instantiated and all its properties are initialized, we can create the rest of the methods it will contain. The methods we will be creating will help this object handle all of our Ajax requests and delegate the server-side responses to the correct callback methods. The method we will use the most throughout our web application is the Update method. This method will handle making all the requests and delegating all the responses to the appropriate callback methods. The object takes three parameters to provide maximum flexibility to our object's XHRs. The first parameter is called method because it represents the method in which we want to handle the requests. As we learned, “The Request", there are three possible values for this parameter: GET, POST, and PUT. The second parameter is a called service. This parameter represents the key/value pair, XML, or any other type of data that we would like to pass to the server side to be saved to a database or used to retrieve specific data. The third is an optional parameter named callback. This parameter represents the callback method that other objects will register to use when making a request. This method can be located in any other object, as long as it is scoped properly during the request. If this parameter is not passed, we default to a callback parameter that we will create as part of the AjaxUpdater object next. The below snapshot shows how the Update method is constructed.
object before we can use the rest of its methods. It also prevents JavaScript from throwing an error because the method will not have existed at this point.
This method initializes the AjaxUpdater and, although it does not accept any parameters, it is used to set all the
local properties for the object. If this object is not initialized, the properties of the object will not be properly instantiated when we try to
access their values, resulting in unexpected behaviors. Creating a property in a Singleton object is as simple as typing the name of the object, followed by
the property you want to create.
AjaxUpdater.isUpdating = false;
In the preceding example, we are creating a Boolean property named isUpdating. This property is set to false by default because the object is not currently active, which means that it is not currently updating any requests or waiting for any responses. The isUpdating Boolean will be used to determine whether the object is currently updating a request or waiting for a response from the Ajax engine. This property will be extremely useful when we have an application with numerous requests because we might need to decide whether to make a new request based on its value, or we might want to check it if a user is trying to exit the page while a request is in transit to warn him of any potential data loss. There are many other uses for this Boolean value, as we will discover when our application grows larger and has numerous active requests. After we have our object instantiated and all its properties are initialized, we can create the rest of the methods it will contain. The methods we will be creating will help this object handle all of our Ajax requests and delegate the server-side responses to the correct callback methods. The method we will use the most throughout our web application is the Update method. This method will handle making all the requests and delegating all the responses to the appropriate callback methods. The object takes three parameters to provide maximum flexibility to our object's XHRs. The first parameter is called method because it represents the method in which we want to handle the requests. As we learned, “The Request", there are three possible values for this parameter: GET, POST, and PUT. The second parameter is a called service. This parameter represents the key/value pair, XML, or any other type of data that we would like to pass to the server side to be saved to a database or used to retrieve specific data. The third is an optional parameter named callback. This parameter represents the callback method that other objects will register to use when making a request. This method can be located in any other object, as long as it is scoped properly during the request. If this parameter is not passed, we default to a callback parameter that we will create as part of the AjaxUpdater object next. The below snapshot shows how the Update method is constructed.
2.The Update Method in the AjaxUpdater (AjaxUpdater.js)
AjaxUpdater.Update = function(method , service, callback)
{
if(callback == undefined || callback == "")
{
callback = AjaxUpdater.onResponse;
}
Ajax.makeRequest(method, service, callback);
AjaxUpdater.isUpdating = true;
}
The first section of code in the Update method is an if statement, which checks for the callback parameter. We check to see if this value is undefined or an empty string. If it is, we set it to a default method named onResponse, which is a method that will exist in the AjaxUpdater object. When we are sure that we have a callback method set, we move on to make our XHR through the Ajax
object. We already know how the engine handles XHRs at this point the
only difference here is that we are encapsulating it into our new AjaxUpdater object and abstracting the Ajax object from the rest of our application. As I mentioned at the beginning of this section, the Ajax object also uses the Singleton pattern because we do not want multiple Ajax objects floating around a large web application because it would get very unwieldy. The XHR is made by directly calling the Ajax object's makeRequest
method and passing it three parameters. The first parameter is the
method in which we want to send the data, which we have passed to the Update method. The second parameter is the service parameter that we passed to the Update
method, which contains an XML or server-side file and additional query
strings. The last parameter is the callback method that was either
passed to the Update method or set to the default response method in the if
statement. This method will make an XHR according to the data we
provide it and respond to the callback method we pass to it, regardless
of where it is located in the application. As you can see, we are also
setting the isUpdating Boolean from the initialize method to TRue based on the fact that a request is in progress when this method is invoked.
The onResponse
method that we use as a default callback method is very simple and can
be used for any default response that you would like; see the below code
snapshot, In the example, I am simply using it as a way to reset the isUpdating Boolean back to false, but you could use it to display a default, custom loading message, and so on.
3.The onResponse Method in the AjaxUpdater (AjaxUpdater.js)
AjaxUpdater.onResponse = function()
{
if(Ajax.checkReadyState('loading') == "OK"){AjaxUpdater.isUpdating = false;
}
}
If we do not use this default callback method, we will need another way to set the isUpdating Boolean to false. I have decided to set this variable directly in the Ajax object's checkReadyState method. When the readyState of the response reaches level 4, we know that the response has completed and is no longer updating. The below snapshot shows an example of where to add this code to the existing method.