Whether you’re working with websites or applications, you’re bound to have faced a task dealing with Ajax requests, whether it be getting a new document’s content or fetching updated JSON data. You’re bound to have also used some form of library to gloss over the mess of an implementation XHR is.
There are a tonne of libraries, and a few decent XHR modules that allow you to make simple XHRs. Working with AngularJS daily I love the syntax for working with XHR, over their $http method:
Angular makes it really easy, and nice and readable, note the shorthand .get() method. It also comes with other methods such as .post(), .put() and .delete() to do the majority of things you need.
I wanted to take this sugar syntax approach and write the simplest cross-browser XHR module I could, so I’ll take you through Atomic.js, which is the result of that.
It all started (interestingly enough) with Microsoft, when they first came up with Ajax technologies, implemented through ActiveXObject. There was then a standardised approach via XMLHttpRequest (XHR) which formed years later, and is now the way we communicate with the servers using Ajax techniques today.
Around the web, you can find scripts like this, for “cross-browser” Ajax (source):
At first, if you’ve never seen what I’d call “raw Ajax”, underneath all the libraries and wrappers, you’re probably wondering what the hell happened. It’s an ugly sight indeed.
So, amongst browsing for simpler solutions, I stumbled upon a GitHub Gist from Jed Schmidt, where an amazing conversation slowly refactored Jed’s initial stab at a very concise supported XHR instance.
I don’t know about you, but that is magic - I love it. It makes a conditional call inside the Constructor based on what Object is available in your browser. Apparently you don’t need the loop Jed implemented above, and you can get away with the above parameter only, which works in IE5.5+. Fantastic.
So I thought I’d start with this great implementation as the base of atomic.js.
All the above does is provide me with a supported instance however, and no actual communication with the server, there’s a little bit more to XHR than that. Here’s how the next steps will pan out, using a GET method and simplified for this example:
Inside onreadystatechange, we need to then look out for the readyState we need. Here’s a list of readyStates and their meanings:
0: Request not initialized
1: Server connection established
2: Request received
3: Processing request
4: Request finished and response is ready
So, we need to check that it’s all okay, we look for 4:
We’ll hopefully get a 200 status code next, which means all is okay. Anything else and something’s probably wrong, or missing from the server, or not authenticated. But for simplicity, we’re all good:
So what about when it fails? We can just put an else function:
All together now:
And that’s pretty much the basics of using XHR!
It’s pretty complex to keep rewriting though, which is why I wanted to wrap it up in a module for simple reuse. Loving the Angular syntax, I thought about doing something like this:
Look familiar? ;)
So working from what we’ve already got above, I created some chained methods for the module, adding in some automatic JSON parsing when available, and ended up with the following (which is atomic.js v1.0.0):
Using atomic.js is just as easy as any other library, except it’s got a very readable syntax, it’s less than 1KB, and punches well above its weight in functionality.
I’ve got some ideas planned for the future development of atomic, and of course feel free to help out!