I don’t know about you, but the word Ajax used to scare me. As a frontend developer, it is nearly impossible avoiding the use of Ajax in your web projects, especially if your application is of dynamic nature. So i wanted to write a post that would be a go-to resource for everything Ajax you might encounter. Well… maybe everything is a bit ambitious! but i promise that by the time you are done with this tutorial, you will have victory over the subject. This post will start from totally beginner, all the way to advanced. If you feel i have left anything out, kindly comment or point it out, so i can also learn or perhaps update this post. Here i will share everything i know about using Ajax, as it has greatly helped me in my own personal and professional work. Like all my posts, this one will be a long one. I have provided links below so you can skip to any section on this topic. I will also be updating this post with time, so do come back if a section you are interested in is not ready or not found. Below is a link to the GIT repo where you can download the sample files for this post. Ready?
https://github.com/scriptonian/ajax-demystified.git
Content List:
- What is Ajax?
- Loading Text or HTML with jQuery
- Loading and reading JSON Data with jQuery
- Taking control with $.ajax()
- Ajax with third party API’s
- JSONP
- Ajax without jQuery ( Native Ajax )
- Working with Ajax Promises
What is Ajax?
Simply put, Ajax is a two way kind of communication that happens between your web browser and a server. It is a fancy term used to describe applications that can request and update data, without the page refreshing. It is very common to see such behavior nowadays, for e.g you click on a button, and the page or section of the page updates without the browser reloading the page. Sounds familiar? This is Ajax in action. The technology has been around for a while. I believe it was introduced in 1999 by Microsoft as part of Internet explorer. Let talk a little bit about client-server communication. When a browser requests for a page from a website(which is located on a server), we refer to the browser as the client. So in other words one can say that the client makes a request to the server and the server responds by returning a page for viewing( E.g you type www.facebook.com in your browser, the request goes to the facebook server, and the server responds back by giving you your facebook page). Lets take an example where we are looking at food recipes. As you scroll down the page you see a “more” button. Chances are you want to see more recipes, so you click on that. In the traditional way, clicking on the “more” button would take you to another page where you can see more recipes. The user experience here is not the greatest as it involves the web browser refreshing its page. These days however, because of the Ajax, we can update the page and show more recipes without the browser refreshing. Why is this beneficial? Well imagine the work done in reloading an entire page. Its quite an effort having to reload everything that is already existing, when we can only request the data we need updated and download only that. Doesn’t that sound more efficient? With Ajax the server send us only the data we need.
AJAX stands for Asynchronous JavaScript and XML. Mouthful and cryptic don’t you think? It is a group of technologies that work together to bring you some of the features i have been talking about. Lets explain the technologies involved here. Asynchronous means that the client(browser) can request new data from the server at anytime and continue it’s execution without waiting for the reply(runs in the background). There are many ways in which this could happen. For example the user clicks on a button, or hovers over an item. There are no page refreshes involved with these actions, yet the request can be made by the client in the background. When a reply is received from the server, a browser event is fired (which we can listen for in our code). The events handling is all done using Javascript. For example, what happens when the server responses back with the data we want? Javascript takes care of that part. What about the XML in Ajax? This can be a little confusing. It doesnt mean you can only use XML with Ajax. An Ajax request can be for Script or text file, JSON Object, XML, or HTML. The XML in Ajax (Or the X in Ajax) comes from a technology called XMLHttpRequest (XHR). It is an API available to web browser scripting languages such as JavaScript. It is used to send HTTP or HTTPS requests to a web server and load the server response data back into the script. So XHR simply enables the browser to send or request data from the server. XHR is the communication technology that exists between the client and the server. It is also worth knowing that there is also another term called AHAH. This stands for Asynchronous HTML and HTTP. But they are all pretty much the same, the main idea with AHAH is that you can use javascript to go grab HTML and insert it somewhere on your page, in response to an event. You can grab data from just about anywhere and use them for desktop or mobile applications.
Understanding how Ajax works its very important before diving into code sample. I hope you have a very clear picture now of what Ajax is and how it works. Knowing what going on “under the hood” helps you think in Ajax.
We will start with how to use jQuery’s Ajax methods in our web applications/sites. Traditionally it would have been best to start off learning Ajax with native javascript. But since most developers find jQuery easy to use, we will start from there. When we are done with the jQuery ways of doing it, we will step our game up and dive into using Ajax natively (if thats what makes you happy). However you can choose to start from using native javascript, just click the link in the post contents above and it will take you directly to it. I am assuming you know jQuery, but you don’t have to be a master. A basic understand is all you need. The rest is persistence and a willingness to learn.
Finally i should mention that you are going to need a server to load your HTML files. Remember that Ajax is a client-server communication technology. That said we already have our client (the browser), but we will need to load our html pages on a server for it to work. Luckily many IDE’s these days come with a built-in local server. One of them is the Brackets IDE by Adobe. This is the one i am using. To run my app, i just click the preview button and the index.html opens up on a built-in server that ships with the IDE. There are many other IDE’s like Cloud9, Atom, Sublime etc. You can even choose to run these examples on JSFiddle. Chances are the IDE you are using already has a plugin local server setup. If you have your own server, then feel free to upload the files using an FTP client and preview the results. Lets get coding!
Loading Text or HTML with jQuery
jQuery is awesome. It provides many methods we can use when working with Ajax. One of the simplest ways is to use its .load() method. This will request an HTML or simple text file from a server and load its data onto your page. Lets setup a simple page to see this. You can find the source code in folder “one” on Github link provided. Our index.html file looks like this.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>jQuery Load</title>
</head>
<body>
<script src="//code.jquery.com/jquery-1.12.0.min.js"></script>
<script src="app.js"></script>
</body>
</html>
This only sets up our page to start using jQuery. To save up on space as i write this post, i wont be typing this HTML code again. All our code will go into the body of this page, or into our app.js file. But i will mention it so you know. It only helps if you have downloaded or checked out the files.
What we want to do is load some data into a div on the page. You can load data anywhere you like. But lets say we have a div on our page named recipe-box.
<div id="recipe-box"></div>
Our recipe box will act as a container where we can load some data into. So make sure this div exists on your page and lets load some data into it. We will write all our code in app.js. Write the following in our app.js file.
$('#recipe-box').load('food.txt');
We used jQuery to find the recipe box div on the page(by targeting its div ID) and loaded the contents of the food text file into. How simple is that? Similarly, we could have used a class on the div as well. Run your app on a server (remember if you dont, you will see an error like this)
Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https, chrome-extension-resource.
This is the error i see in chrome. You might see an error of similar nature if you don’t run this example on a web server. If you are extremely lucky, then chances are you have a browser that does not give you this security warning. In any case, once you get this running, you see a successful message of “Hello, I-am Konstantin! Welcome to your recipe app!”. Great job! You know a little Ajax.
What about HTML data? Well we do it the same way. In the sample code you will find a file called “macaroni-cheese.html”. Lets load the contents of that into another div. Create another div on the page as followers
<div class="todays-special"></div>
In todays special, we will load the entire contents of “macaroni-cheese.html”. We load it the same way as we did for the food text file, only we specify the html file name.
$('.todays-special').load('macaroni-cheese.html');
Notice that this time we targeted a div with a class name(todays-special) to load the data. But it gets even better. What if we wanted to load only parts of an html page into our div. What does this mean? We know we can load the entire html file into some div on our page, but we want to load a specific part in that html file into our page. Not the whole file, a small section of it. jQuery’s load allows us to load fragments of a page. In our project source, we have a file called recipes.html. In there i have two divs, one of which has an id of specials. Lets load only that part in our todays-special container.
$('.todays-special').load('recipes.html #specials');
Reload your page, and voila, only a portion of the page was loaded. Isnt that so cool? Lets takes this a little further. Everything we have seen so far is on page reload, how about we add some links/buttons on our page and make them load data when the user clicks on them. I think this will be even cooler. In our index.html, we have add a nav section.
<nav class="new-recipes">
<a href="fish.html">Fish Recipe</a> ||
<a href="avocado.html">Avocado Recipe</a>
</nav>
Now when you click on a link, we want to load the data from either our fish.html or avocado.html into a display-recipe div located on the page(if you dont have one, then create it). Here is how we implemented that logic in app.js
$('.new-recipes a').on('click', function(evt){
evt.preventDefault();
var url = this.href;
$('.display-recipe').load(url + ' #specials').hide().fadeIn('slow');
});
When the link is clicked we preventDefault to prevent the link from following through (doing a page refresh and going to that page, remember we now hate page refreshes). But have a link there, is good even if we dont want it to follow through, because if the user have disabled javascript, the user can still see the link as it will go to the requested href page(when javascript is disabled we want the user to go to the page). With javascript enabled the user experience becomes better as it will load the data inline without a page refresh, giving our app a modern feel to it. In the code above, I have also added a little animation to hide and slowly fade in the text when the link is clicked. Run the code and see for yourself.
Loading and Reading JSON Data
When it comes to transmitting and receiving data over the internet, probably the most popular format is JSON / JSONP (JSON with padding). They are both the same thing with a few differences (local and remote server access capabilities). If you are going to be using data within your own app, or apps and dont want have to worry about accessing that data externally on other domains, then you would use the JSON format. In other words, if everything is going to take place on one server (your server), then JSON is the way to go. Issues come up however when you try to transmit data between across difference domains. And that why we have JSONP. JSONP is a simple way to overcome browser restrictions when receiving JSON responses from different domains to the client.
jQuery makes it really easy to get JSON data from the same server the page is on and work with that data in your app. This method is .getJSON(). It is defined as followed
jQuery.getJSON( url [, data ] [, success ] )
In the method, the url is a string containing the URL to which the request is sent. data is plain object or string that is sent to the server with the request and success is a callback function that is executed if the response is successful. Note the data and success are optional parameter. Lets see this in action by loading JSON data into our app.
The files for this project can be found in the project folders (folder two). I have a file called data.json that has data profiles for some of the developers on the Ghana Software Developer Group. If you are interested in being on it, join the group and find the post where i ask users to. Other files that you should be concerned about for now are the index.html and app.js files. As you are already aware, app.js is where we will be writing our logic. Lets load data.json into our app, and add a success callback function that alerts us with a message.
$.getJSON('data.json', function(){
alert('data is loaded');
});
The data load successfully, if you run this. If you dont believe me try to load another file, like data2.json and see what happens. The alert message will never show up. Instead of passing the success callback to the getJSON method, we can use chaining to handle success/failure/always callbacks. More of that in a minute. Another way to write the above is to use chaining (a way of attaching multiple methods onto an object in javascript – yes functions are objects also)
$.getJSON('data.json')
.done(callback);
OR
$.getJSON('data.json')
.fail(callback);
OR
$.getJSON('data.json')
.always(callback);
You can even use .done(), .fail() and .always() all at the same time(chaining them back to back).
$.getJSON('data.json')
.done(callback)
.fail(callback) .always(callback);
Also note that you dont have to put the chaining methods on a new line, that is only a developer preference. You could have written it like this $.getJSON(‘data.json’).done(callback). This does the same thing. The done method gets fired only when the response is successfully, the fail when the data cant be retrieved, and always is a little special as it will fire whether or not the data loaded. It fires when the request has completed (so it may or may not be very useful). Here we can rewrite our initial getJSON method like this
$.getJSON('data.json')
.done(function(){ alert('data is loaded'); });
This will work just like the first implementation. Lets move on with getting data from the callback (this is where things begin to get interesting). When the success event is fired, we can pass it a param to which it stores the data retrieved (the response data).
$.getJSON('data.json', function(data){
console.log(data);
});
Notice here we have passed in a data param to the callback. When the callback is successful, data gets passed/stored to this object. Remember how client-server interaction works? A request was made, and the response came back with some data. We are capturing that data and logging the results in our console. We see an array of objects! [Object, Object, Object, Object, Object, Object]. I only have 6 objects in my JSON(as of the time of writing) so that is what we see. Remember it is an array of objects, and you can you potential check to see its length (arrays have a length property). For eg, if the length is 0, it means there was no data returned.
{
"name": "Peter Sonny Fraikue",
"avatar": "DEFAULT_IMAGE",
"occupation": "Frontend Dev",
"short_bio":"I love to code"
}
Each object returned has key / value pair properties, and this allows as to grab values any of them as we parse the data. For each object, we can grab the data that we want, for eg, the name of the developer, and use it for anything you want(like displaying it). So how do we parse this data? We can use the jQuery each method to parse the response object. Lets see this in action. Please pay attention here.
$.getJSON('data.json', function(data) {
var output = '<ul>';
$.each(JSON.parse(data), function(index, element) {
output += '<li>' + element.name + '</li>';
});
output += '</ul>';
//write the output content into the container div
$('#devContainer').html(output);
});
Lets see what is going on. We know how to load json data into our app, and respond to when the data has loaded successfully. In our callback, all we are doing is building some HTML string. We create an unordered list element(<ul>) and use jquery’s each method to grab the property value we are interested in(name) and append it to a list element(<li>). We loop through the response object, grab the data, and display the data in an html element. I should also mention that we have wrapped our data around the JSON.parse method. This will ensure that we are converting the string data into a javascript object. Its fairly simply. Here are the results when we run the page.
jQuery is very powerful and you can use your existing knowledge of it to do whatever you like after you retrieve the data. You can do things like animate the data into view, hide/show, etc. Using this knowledge we can build a plethora of applications, because we know how to get the data into our application. One classic way you will see ajax being used, is when you do search on google. As you type the search term, we instantly get feedback with suggested results. This is all Ajax. Lets see how we might construct such an app. We will call it Prooggle. Like google its a search engine for programmers all over the world. Ok ok… programmers from Ghana.
The files for this project can be found in the project repository (folder three).
In the index.html file, i have created a very simple input text box where we are going to type our search term. Familiarize yourself with it by poking around the file. In the app.js, i have updated the code to display more information. Its doing pretty much the same thing did last, i.e. its building an html string and displaying the object data in html elements. We are displaying the name, image and short bio. View the html page and see how the JSON data is loading successful on the page. To continue working with me, open search.html and search-app.js. This will continue from where we left off. I have intentionally left index.html for you to review, so we will be continuing in search.html.
Lets re-cap what we are trying to do here. A user comes our page to search for an awesome developer. They start typing, and we expect our auto suggest feature to return results. This means that our input text box is what will actually trigger our ajax search! Thats where it all begins. When we type in the box, we want to fire a keyboard event. We want the event to fire when the user releases their finger from the keyboard. We use jQuery’s keyup event. An example of using this event looks like this
$( "#user_input" ).keyup(function() {
console.log( "Handler for .keyup() called." );
});
When user_input text box receives an even that the users finger has moved up from a keypress, it logs a message to the console. What we want to do here is wrap our AJAX calls around this event. When the finger comes up, we fire the ajax call. Lets see how that code looks like (located in search-app.js)
$('#prog_search').keyup(function(){
$.getJSON('data.json', function(data) {
console.log(data);
var output = '<ul>';
$.each(JSON.parse(data), function(index, element) {
output += '<li>';
output += '<h2>' + element.name + '</h2>';
output += '<img src="' + element.avatar + '" width="80" height="80" />';
output += '<p>' + element.short_bio + '</p>';
output += '</li>';
});
output += '</ul>';
//write the output content into the container div
$('#autosuggest').html(output);
});
});
Notice that i have wrapped our code around the keyup event that i showed you earlier. For now, when you click on any key, our ajax method will be fired. But we want to do more than that. We want to get the actual text that the user has typed first, and do a search in our json response data, and display those results.
Lets come up with an algorithm for doing this search. A user types in some data in the search field, we want to capture what they have entered. Once we do this we want to search our response object for strings that match what the user has typed. There are many ways we can do this. We will be looking at how you can do it with regular expressions. The reason why we are choosing to use this is because it allows us to do case insensitive searches, where as other methods would do case sensitive search. It doesn’t matter if the use uses a capital KONSTANTIN or a lower case konstantin, we want results for either (the are the same to use and we want that included in our results). Lets create these steps in our algorithm. First lets get the value of what the user has inputted.
var searchText = $('#prog_search').val();
Now that we have a value, we want to make sure its the lowercase version we use. We use our regular expression this way
var regEx = RegExp(searchText, 'i');
or
searchText.toLowercase();
This will grab the value of searchText, and return the case insensitive version. Another way we could have do this is to use the toLowerCase method of the string prototype. This will take a string value and convert it to lowercase.
Ok so we have the string we want to search for, because that is what the user has typed. Where do we search for it? In our response object of course. Remember before when we used jQuery’s each method to parse through the returned data? As we parsed each object we were able to extract certain pieces of information, like the name, short_bio, etc and display those. This is where we search. We decide what property we want to compare, to what the user has typed. If they user has typed “konstantin” and we want to search all “name” properties during our loop, then that is what we do. For each object, we do a string comparison to any property value. We can even search ALL properties on the response object. For our app, we want to search the name property. Let see what we do inside the each
$.each(JSON.parse(data), function(index, element) {
//search the name property
if(element.name.search(finalText) != -1) {
//build out html string
}
}
We are adding onto the jQuery .each method we saw earlier. The new addition is bolded above. In each object we grab the name and run the search method(which takes in a regular expression as a param) on the name. If there is NO match, we get a returned value of -1 from the method. So what we are doing here is just checking to make sure -1 was not return. Anything else means that a match was found! If found, we proceed 🙂
We can also modify this if statement to search more properties. Currently we are only searching through the name property, but what if we wanted our search to include the developers occupation or bio? We can add these conditions to the if statement. We can upgrade our if statement to something like this
$.each(JSON.parse(data), function(index, element) {
if( (element.name.search(finalText) != -1)
|| (element.short_bio.search(finalText) != -1) ) {
//build out html string
}
}
We add an OR operator || to check another condition. Our entire code now looks like this
$('#prog_search').keyup(function(){
var searchText = $('#prog_search').val();
var finalText = new RegExp(searchText, 'i');
$.getJSON('data.json', function(data) {
var output = '<ul>';
$.each(JSON.parse(data), function(index, element) {
if(element.name.search(finalText) != -1) {
output += '<li>';
output += '<h2>' + element.name + '</h2>';
output += '<img src="' + element.avatar + '" width="80" height="80" />';
output += '<p>' + element.short_bio + '</p>';
output += '</li>';
}
});
output += '</ul>';
//write the output content into the container div
$('#autosuggest').html(output);
});
});
Pretty neat dont you think? Implementing a live / auto search in your apps can only be accomplished with about 30 lines of code. Of course if you need super advanced features, you can look into using a library for that. Lets keep going, there is so much more to learn.
Taking control with $.ajax()
There is one more method i will like to talk about. jQuery provides use with an ajax method that gives us more control when it comes to loading data into our apps. The funny part about this method is that you have been using it all along. When we used load() and getJSON(), it uses this ajax method behind the scenes! Those methods are only shorthand. They make it very easy and convenient for us to make ajax requests. Sometimes this is not what we want. So lets take back our power and fine tune how we make ajax calls. The $.ajax() method has probably over 30 different settings you can use to customize your request. Lets look at some settings one might want to set when they are making a request to a server.
type: can be used to set ‘GET’ or ‘POST’ depending on how the request is made
data: we want to send data to the server with our request
timeout: we can tell the request how long to take before timing out
beforeSend: perhaps you want to call a function before the request is made.
See the complete options here. Thats a big list isnt it? Try to just glance over them before proceeding.
Ok, lets re-write our Prooggle app with $.ajax. The source code for this is in the ‘four’ folder. What we do… is simple, we completely remove the $.getJSON method and replace it with our brand new give me back my power $.ajax method.
$.ajax({
type: 'GET',
url: data_url,
timeout: 3000,
success: function(data){
console.log(data.length);
var output = '<ul class="pList">';
$.each(JSON.parse(data), function(index, element) {
if(element.name.search(finalText) != -1) {
output += '<li>';
output += '<h2>' + element.name + '</h2>';
output += '<img src="' + element.avatar + '" width="80" height="80" />';
output += '<p>' + element.short_bio + '</p>';
output += '</li>';
}
});
output += '</ul>';
//write the output content into the container div
$('#autosuggest').html(output);
},
fail: function(){
console.log('This function gets executed when the request fails');
},
beforeSend: function() {
console.log('This function will run before the AJAX request is made')
},
complete: function(){
console.log('This function will run after the success method has finished')
}
});
Do not be afraid by what you see. You have already seen the success method in action. I only copied an pasted from our old code(which you have now mastered). The only thing different here is how the $.ajax method is constructed. The method takes an object or key value pairs. Like this $.ajax({ key: value, key: value,}). Thats it! The keys are a little special however ( success, fail, complete (see them bolded in code above) ). In these keys we have callback functions that get executed when those events fire (nothing fancy there). See how much more control we have gained over the request? We are able to do so much more using this new method than previously. This really gives us a lot of power. Choose which ever Ajax method you would like to use based on your app needs.
Ajax with third party API’s
Working with third party API’s is very exciting. What some companies do, is provide you with tools that enable you to connect their websites ( like Twitter, Facebook, Google, Github, IMDB, etc. ) so you can pull and use data from their site for your app purposes. The data can include profile information, tweets/statuses, and many more. API’s have allowed developers to build on top of other platforms, hence creating new genres of applications. Data really is king! But as exciting as this can be, it can be quite complicated to get it, if the third party is strict about how you access it.
For example they can ask you to authenticate before any kind of access to data is given to you. There are reasons they do this ( to protect themselves ). Hackers out there with bad intent may misuse their API in ways it was not intended for. Because of this, one might have to go through some initial setup before they can gain access to third party data. What you need to know right now is that, once that initial setup is done, grabbing and using javascript/ jQuery to process that data for your app is done the same way. Yes we have already learned how.
You may or may not have heard of OAuth. It is a simple way to publish and interact with protected data. It’s also a safer and more secure way for people to give you access to their data. Many companies use this. Like i said before it requires some setup. I will leave this setup to you (evil laugh, ….you! do the dirty work). Depending on which api you decide to use, for eg twitter, you can find developer documentation on the website on how to set it up. Ok ok, i am not a mean person, if its really important to you i teach how to do this setup, do let me know. If many are interested, i will be sure to write a post on it. Or i would potentially add another chapter to this series on how to use OAuth with Twitter, Facebook or Google. Remember the core of this tutorial is to teach you how to use Ajax, not how to setup something like OAuth.
The APIs we will use in this tutorial DONT require us to use any kind of authentication. We just call the url with some parameters and voila! We get data back we can use in our application, in JSON format! We will be using the Github API service to pull information about any user we want ( as long as we know their user name). The app is simple, you type in the name of the Github user, and it will list all the repos this user has. It will also provide extra information about the user. This example demonstrates what you would normally think of when you need an api for your app. For example, i want to list all the tweets made by a user; or i want to see a list of all the friends a facebook user has, etc. You will then build an interface that enables a user to perhaps interact with. Our app only has a text box and an blank area where the results will get displayed. Lets look at this Github API. Go to this URL,
https://api.github.com/users/scriptonian
What do you see? You see some JSON data returned to the page. The user name “scriptonian” is my name. If you have a Github account, go ahead and replace my name with yours, and see repo information about your account. This is the public interface Github gives us. By simply calling a url, we get the data we need. We get information like avatar url, location of the user, how many repos they have, how many users are following them and many many more. Once you have all your initial setup done, the rest of the work is basically calling these URLS, passing in some data and you get the data you need returned. The format for getting a Github user info is
https://api.github.com/users/USER_NAME/
If you wanted to get more detailed information about repos, like how many there are, you can use this url
https://api.github.com/users/USER_NAME/repos
We go into the /repos path for that user. Githubs API provides many wonderful tools. Note however that not all data will be available publicly, without you doing some extra setup. For instance, if you wanted to create an application that creates new Github repos, this is something that might require you to authenticate before you can do anything. Imagine having a random user create repos in your account. Not cool now is it? However to get basic information, we can do that without any hustle. Thats a lot of talking, lets see some code.
The files for this project can be found in folder ‘five’ in the repo. In the index.html file we have a very basic form. It takes a username, which is the name of the Github user, and it will return profile information when the button is clicked. In the app.js file, we will write our logic to handle this button click.
The first thing we want to do is see if our application can receive JSON data. Because without data, we dont have an app. When the user clicks on the button, we make an Ajax call and we console log the returned results. Sounds like something you can do huh? You bet. Lets do that. Update your app.js
$('#git_handle').submit(function(evt){
evt.preventDefault();
$.getJSON('https://api.github.com/users/scriptonian', function(data) {
console.log(data);
});
});
In app.js, we have added the following code. Using jQuery we write a submit event handler for the button. When the button is clicked we assume for now that the user is searching for my repo (scriptonian). Run the app and click on the button (be sure have your console window opened).
We see that our console reports back that the data was successfully received! This is really exciting. Because once we have data, imagination is our only limitation. Lets move forward.
The next thing we want to do, is have the user type in any Github user they want, and see if that returns anything. Lets try that. All we need to do is grab the value of the input field and append that value to our url. We can make our ajax call from there. Lets see how i did that
$('#git_handle').submit(function(evt){
evt.preventDefault();
//define a base url for api
var baseapiURL = "https://api.github.com/users/";
//get the value of the input
var git_user = $('#gituser').val();
//concatenate the url with user
var git_user_url = baseapiURL + git_user;
//make the ajax call
$.getJSON(git_user_url, function(data) {
console.log(data);
}).fail(function(jqxhr, textStatus, error){
var err = textStatus + ", " + error;
console.log( "Request Failed: " + err );
});
});
The above is very simple. All i am doing is grabbing the value of what the user has typed, and i use that to make my ajax call. I have defined some variables to help me format the final url (baseapiURL, git_user, git_user_url). You will also notice that i chained my ajax call to handle failures as well. If the call fails, we might want to do something. Like show a message on the screen that the user does not exist ( you can do whatever you want ). As you can see the fail callback takes some arguments and reports to our console if the call fails. Try and break the app! Click on the button without typing any Git username. What happens? We get this error
Request Failed: error, Not Found
We get a status message of “error” and an error of “Not Found” when we click the button. The ajax call is made after button click, and our fail method catches that there is something wrong. You can use this to your advantage. If an error message comes back, you can write or show an alert message to tell the user something went wrong. Let enhance this just a little bit. I am going to re-write our fail method to output “user not found” if the error message is “Not found”. Our new getJSON method looks like this
$.getJSON(git_user_url, function(data, textStatus, jqXHR) {
console.log(data);
}).fail(function(jqxhr, textStatus, error){
var err = textStatus + ", " + error,
noUser = "<p>User Not Found</p>",
unknown = "<p>Sorry something went wrong</p>";
if(error == "Not Found") {
//use jquery to append
$errorBox.append(noUser);
} else {
//use jquery to append
$errorBox.append(unknown);
}
});
We have declared some string variables that hold possible fail messages. If the error message is “Not Found” we write “User Not Found” below our form, if something else funky happens, then we simply write “Sorry something went wrong” on the page. Its good to give your users feedback as to what is happening. This way they are not waiting. Now that we have handled our fail method, let expand on our success method.
What do we want to happen when a user is found, or the Ajax call is successful? We can do just about ANYTHING, as long as we know what data we want to display. When a user is searched we want to see ALL public repos they have. We want the name, language, stargazers_count, and perhaps the users avatar. We will display this in a custom HTML. Remember this is only my choice. When you decide on what you want to do with your app, and can confirm that data is available through the API, the rest is just writing your HTML to display that data. So lets see how to write that and move on to the next section.
$.getJSON(git_user_url, function(data) {
console.log("success");
var avatar = data[0].owner.avatar_url,
output='',
avatar = '<img src="' + avatar + '" height="100" width="100" />';
$.each(data, function(index, element) {
output += '<section class="user_display">';
output += '<div class="result_name">';
output += (index+1) + ". " + data[index].name;
output += '</div>';
output += '<div>';
output += data[index].stargazers_count;
output += '</div>';
output += '<div class="result_language">';
output += data[index].language;
output += '</div>';
output += '<div>';
output += data[index].html_url;
output += '</div>';
output += '</section>';
}); //end each var finalHTML = avatar + output; $dataContainer.append(finalHTML);
})
Here is what our getJSON now looks like. I advice you look in the repo for the complete code. The HTML doesnt look so pretty when mixed with javascript i agree. BUT this brings up an opportunity to talk about possible solutions. There are many Javascript templating languages that help with this. My personal favorite is Mustache. It allows you to create an html template (which you do in your index.html) versus doing it in javascript. Once you have your JSON data, you can just pass it to the template to render. Its super cool and convenient. Lets get back to our code. I updated the git_user_url to point to the API’s repos resource. This returns a list of all the repos that user name ( i mentioned this before, scroll up ). I get the first data returned(in the array) only so i can get avatar image (i could have done this many different ways). Then i parse through all the repos(our JSON data returned) and display some basic information in my custom HTML (displayed in divs). When i am done, i append it to my data container. How simple is that? There is nothing here you have not seen. You can preview the app here. Thats pretty much it with grabbing third party data.
JSONP
Earlier on in our Ajax journey we heard about JSONP. Browsers have what we call same domain policy. This is just a way to say the data you request MUST also be on that same server/site you are requesting from. The files for this chapter is located in folder ‘six’. Lets try something out. I have some json data located on my server. Lets write an app that makes a call to get this json data from our desktop and see what happens. The code can be found in test.js
var external_json = "http://scripton.net/gsd/search/data.json";
$.getJSON(external_json, function(data) {
console.log(data);
});
We get this error that looks like this
XMLHttpRequest cannot load http://scripton.net/gsd/search/data.json. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:53795' is therefore not allowed access.
This is because of that same domain policy we spoke about. What we are trying to load is not in the same place as we are calling it. Some browsers may allow you to do that however. Now what is the way around this? We use a technique called JSONP. That is all it is. The technique involves adding a script tag to a web page that will load JSON data from another server. The reason this works is there are no restrictions against loading external scripts. In JSONP, we pad our object in a function call. I have created a JSONP resource here
http://scripton.net/gsd/jsonp/jsonp.json
Do you notice any difference between this file and the first one we saw above (external_json)? I have provided the file in our project source. This JSON file is wrapped around a function call, called dataHander. And our data is defined within that function. This is the “padding” in JSON!
dataHandler( [
//PADDING goes here
] );
The function takes an object. When this script loaded on our page, that dataHandler function will get executed. Please see the jsonp.html file. In there i have two scripts loading(note the order in which they load matters)
<script src="app.js"></script>
<script src="http://scripton.net/gsd/jsonp/jsonp.json"></script>
In our app.js, we define our dataHandler function. We do this because we want it to exist BEFORE the JSONP file is requested. Remember as soon as that file loads, it will execute the dataHandler function, which is defined in app.js like this
function dataHandler(data){
var output = '<ul>';
$.each(data, function(index, element) {
output += '<li>' + element.name + '</li>';
});
output += '</ul>';
//write the output content into the container div
$('#jsonpContainer').html(output);
}
Notice we have not made a single Ajax call yet. We have only requested the data as a script. As soon as the second script in our html loads, it executes our function. You have tricked the page into loading the JSON data as a script.
Lets look at another way of doing this. What if you dont have access to that JSONP file but you want to use it? There are certain things that may help your case. If the author of that JSON file has a JSONP function wrapped around that JSON data, then perhaps they can let u know what the function callback is. You can even determine it yourself if you have the JSON url. You can also use jQuery, we makes it really simple. In the project files, please find jquery-jsonp.html. You can see how its being handled there. You can also look in the jQuery documentation…or just ask questions on here. Lets move on!
Next we will see how to ditch jQuery to make Ajax calls. Some of you are purists, i know. So get ready for jquery-less Ajax (if there is even such word)
Ajax without jQuery ( Native Ajax )
Maybe you dont want to use a third party library like jQuery to make Ajax calls. What do you do? Well, all is not lost. Under the hood, jQuery is javascript after all, and its API’s only make working with javascript easier. You should not forget also, that jQuery is doing a lot for you, so if you decide not to use it, you will have to write a lot more code, like handling browser inconsistencies etc (which might not be worth your time). Choosing to write pure javascript means you just have to understand how the browser does asynchronous operations behind the scenes. Browsers use what we the call XMLHttpRequest object to make requests. And when the server responds, that same object is used to process what is returned. Here is how its done
First create an instance of the XMLHttpRequest object
var myXHR = new XMLHttpRequest();
Next the XMLHttpRequest objects open method is called. It takes in 3 params ( http method, the url request, and a boolean flag if its asynchronous ). You can think of this as opening a connection to the JSON data (file) we want.
myXHR.open('GET', 'data.json', true);
Then we write the handler for what happens if our call is successful
myXHR.onload = function() {
if(myXHR.status === 200) {
//it was successful process results
console.log(myXHR);
}
}
Finally we send our request
myXHR.send();
That is the basic setup! We can use our console to inspect this myXHR object. Lets take a peek when the request is a success (status 200). We can see things such as status of the request, the response Text and many more. Notice also there are such things as events that you can see, like onload and onreadystatechange.
Once we have data, the whole world belongs to us. If we wanted we can dump all our JSON data onto the page, we can do that using the document.writeln in our onload handler.
document.writeln(myXHR.responseText);
Here is what you will see
Please note, i dont not recommend you use document.writeln in your production code. This one line is for demo purposes only. We will see how to properly do this. Find this code in the dump.html file in the project folder.
When doing Ajax requests natively, we are particularly interested for when the onreadstatechange event fires. If the value is 4 then the request has been completed, and we can finally do something with the data. Lets modify our code.
var myXHR = new XMLHttpRequest();
myXHR.open('GET', 'data.json', true);
myXHR.onreadystatechange = function(){
if(myXHR.status === 200 && myXHR.readyState===4) {
console.log(myXHR);
}
}
myXHR.send();
This code can be found in the request.js file in our project. What i have done is added the onreadystatechange event to our request object, and moved our status 200 code into that function. If we run request.html, we still see the object in our console…THIS however is a much better way of making ajax requests natively.
When working for older browsers, we have to check to see if that browser has an XHR request object. In the request.js file i have added some code that does this. You can use them in your projects if you are doing ajax natively
if (window.XMLHttpRequest) {
myXHR = new XMLHttpRequest();
} else {
myXHR = new ActiveXObject("Microsoft.XMLHTTP");
}
This makes your code more compatible with older browsers. If the XMLHttpRequest object does not exist then it must be an implementation by microsoft, and that will be used instead.
Earlier on i mentioned i would not use document.writeln to write data onto our page. Lets look at a better way of doing this. The code for this section is found in parsing.html and parsing.js. I have added a div our to HTML file. And we will use native javascript code to write some data on our page. Inside our on ready state, i have updated the code as followers
if(myXHR.status === 200 && myXHR.readyState===4) {
var container = document.getElementById('ajaxContent');
container.innerHTML = myXHR.responseText;
}
All we are doing is getting the div on the page(using getElementById) and then writing the response text into that div. Simple enough? Dont need to speak more on that. Lets see how to parse our JSON data as this is more real world.
In our on ready state change, lets update as follows
if(myXHR.status === 200 && myXHR.readyState===4) {
var container = document.getElementById('ajaxContent');
var devs = JSON.parse(myXHR.responseText);
var output = '<ul>';
for( var dev in devs) {
output += '<li>' + devs[dev].name + '</li>';
}
output += '</ul>';
//write the output content into the container div
container.innerHTML = output;
}
Does this look familiar to you? Because it should. In our on ready state change we save our JSON string to an object by using JSON.parse. Now that we have an object from the string, we can use enumeration to loop through our object. As we loop, we write our HTML output and when done append it to the innerHTML of our container div. Easy and ABC.
Not that this is all happening on page load. Just like we saw in the jQuery section, we can wire this up to a button click and many more. Things are about to get interesting. Lets dive into promises. I am so excited. Its gonna be a long one.
Javascript Promises
Javascript Promises are a much needed feature to have. They address a problem known as callback hell, which one is bound to face if they do any kind of asynchronous programming. As a web developer, this is something you cannot run away from as the browsers internal operations are asynchronous.
So what is a promise? A javascript promise is simply an object that is used as a placeholder for an asynchronous operation. Such operations are for eg when we create or read a file on a disk, or make an HTTP request, etc. When we do this we are running an asynchronous function, that takes in a callback to be executed when its done. The moment we call an async function(operation), we immediately return what we call a promise. When this operation is done the promise will be resolved or rejected. Promises give us a flexible way to hand asynchronous calls. So lets take a look at how we can use promises in our application to make ajax calls. Lets see how we can re-write one of our ajax requests to our data.json file using promises.
function getGhanaSofwareDevs(){
return $.getJSON('data.json');
}
//call funtion at attach promise
getGhanaSofwareDevs()
.then(function(){
// if asynch operation was successful
}), function(data){
//if there is an error
};
Here we have a function called getGhanaSofwareDevs. Notice that this time we are not using callbacks in our jquery getJSON function. Instead the when the function is immediately run, it returns the asyn operation called promise, and we attach our callback functions to that. Our callbacks being success and failure callbacks. Take a look at folder eight in our project file direction. Run the example and check out that our console returns back the objects from the json file(meaning our jQuery promise is working). Its important to understand the goal of this methodology is to give whoever is calling the async operation the responsibility to wire up the callback. This is what makes promises so powerful. We attach our callbacks by using the then() method on the promise object. The .then() method takes two parameters. The first is the handler a fulfilled state. The second for when rejected.
This is barely scratching the surface of what promises can do. If you want to know more, check out my more in-depth post on this subject.
Multiple Ajax Calls
So lets talk about how to better hand multiple Ajax calls without your applications. You may notice that in your application, you might have Ajax calls scattered all over the place. What if you wanted to combine them into a single more effective architecture? For instance, you have 4 buttons in your application. All 4 of them make difference Ajax calls to grab different sets of data. To add on to that, what if you had other javascript files that also made those same ajax calls? This may work for you, but it may not be the most efficient way of handling your Ajax calls. Maintenance becomes a chance in this case. Consider this… how about creating a single javascript file that would hold all your Ajax calls. This will give us more flexible, and we can even reuse this data provider file in other applications. With this new knowledge on promises, are data provider returns a promise to whoever calls them, and they can handle the async operation as needed. Lets see how this might look like
var dataProvider = function(){
//declare all serverice urls here
var theGhanaDevUrl = 'data.json';
//declare service methods here
getGhanaSofwareDevs = function() {
return $.getJSON(theGhanaDevUrl);
};
return {
getGhanaSofwareDevs : getGhanaSofwareDevs
};
}();
The data provider file is invoked immediately when the page runs, and returns a public API we can call upon. Find the files index2.html, app2.js and dataprovider.js. We can now call our data provider anywhere in our app (note that it is declared before app2.js, so the dataProvider global variable is available). We can use it in our app2.js
dataProvider.getGhanaSofwareDevs()
.then(function(data) {
console.log(data);
}), function(err){
//if there is an error
};
Simultaneous calls with $.when()
As applications become more and more demanding, we find the need to do many things at the same time. Imagine this is what we wanted to in our app: First find all developers on the ghana sofware group, then for each of them find their twitter handle and go grab the latest post on by that user; THEN who knows, do something with that data. The possibilities are endless. But they require making multiple ajax requests. We can chain these series of Ajax calls. If something fails (like one of the calls fails) we are not able to display the data we want. jQuery gives us the ability to chain multiple ajax calls. It manages calling and making sure that all of them are resolved before proceeding to run our success callback. The syntax is as follows
$.when(my_ajax_call).then(function(data, textStatus, jqXHR){
//success
}, function(){
//fail
});
The $.when takes in all the calls you want to make. And after performing all the operations THEN calls the .then() method. We are only performing one here. I did that to show you that when a success callback is fired, that function has 3 params. The first being the data object. So in making multiple calls, for eg
$.when(ajax_one, ajax_two).then(function(oneData, twoData){
//success
}, function(){
//fail
});
Both oneData and twoData have an array of items if we choose to access them. Remember in the first example the callback returns data, statusText & jqXHR. So in our success, if we wanted the data object, we would get that like this
var myFirstData = oneData[0];
This gets the data we are interested in. I have provided a sample document on how we can do this in the project files.
Promises are very powerful. And we have only scratched the surface with it. If you are interested in learning more, check out post on javascript promises here (currently being written).
Conclusion
Ajax is powerful! There is no doubt about it. As frontend developers we cant escape from using this technology. I hope you found this post interesting. I want to hear what kind of ajax applications you are building and what libraries you are using. It hard to cover everything and i did my best. Do educate me if something is missing or i could do something better. Take care! Feel free to reach out on twitter as well ( @scriptonian ) if you have any questions.