Ajax is a fairly broad technology with so many different client side and server side approaches that it’s hard to provide generic best practice rules. This however is one.
Requests via ajax tend to be handled asynchronously these days, communicating with the server whilst keeping the user interface active and responsive. This approach provides a potential problem though as it is possible to make a request and not worry about results, presuming what was sent just worked.
Better practice is to always respond from the server and at least have some form of simple logging at the client side so you can be certain communication is working as expected. It is simple for the server to respond with JSON in the form of:
{success:1}
This provides several pieces of information. Firstly the server action completed and was not met with an error such as error 500 (server error) or error 404 (page not found). Also if we toggle the “success” value with true or false, depending on the success of the request, we know that the process we requested was successful or failed. In one small line we rule out several potential points of failure.
Note that most major JavaScript libraries provide a simple means of handling success and failure so this is not hard to implement. In the case of Prototype you need only look at the “onError” and “onSuccess” attributes when defining the initial Ajax request.
In most languages there is a means of building strings and printing out messages. Many will find the printf command all too familiar. In the JavaScript space however things have been a little slow to develop.
We have our strings and to build them up we merely start adding them together but as our code gets more elaborate this gets harder and harder. The biggest problem is usually trying to figure out how to escape quotes and inverted commas as we swap back and forth between plain strings and JavaScript variables.
I’ve often thought there must be a better way and working with the Dojo toolkit there is. It can be found in the method “dojo.string.substitute”. This mirrors the idea used in other languages of passing the method a template string and an object of values to substitute in. Whilst Dojo allows for numerous ways of passing the data such as arrays and functions the one that interests me the most is a standard JavaScript object which is effectively a hash map of name and value pairs.
Here’s a simplified version of the Dojo function that only uses objects for the value map.
var data = {name:"bob", occupation: "builder"};
var string = "His name is "+data.name+" and is occupation is "+data.occupation+".";
Here we merely add the different parts of the string and string values together. Simple enough in a string this size but as it grows and we start working with HTML syntax things get more complicated.
Using the substitute way:
var data = {name:"bob", occupation: "builder"};
var template = "His name is ${name} and is occupation is ${occupation}.";
var str = tfg.string.substitute(template, data);
Here anything surrounded by the format “${something}” is replaced with the value found in “data.something”.
A major advantage of this approach is when we start looking at fetching JSON data sets from a remote server via Ajax. We almost always have to process the return values into something to display and if it is looping through a list of objects we can now define the template once and repeatedly create a string with our substitute method. Here’s a simple idea using JQuery for the loop.
var result = [{name:"a",company:"1"},{name:"b",company:"2"}];
var template = "<tr><td>${name}</td><td>${company}</td></tr>";
var rows = $.map(result, function(index, item){
return tfg.string.substitute(template, item);
})
var tableBodyString = rows.join("\n");
Here we looped through the items substituting each new set of values and pushing the result into an array. At the end we merge the array into a single string with “join” and have the body of a HTML table ready to be used in the page.
This approach is fast, easier to read and much cleaner to implement when looping through data.