Chapter 9 - Classes and Objects

The second line in our makeRequest function says this:

new XMLHttpRequest();

The keyword new in JS is used to instantiate (create) an object. So just like before, when we had this expression:

var peleg = {};

create a literal object for us, this time we're going to create an object in a more unique way -- by using a constructor method.

In Object Oriented Programming (OOP), we have classes and objects. Objects are just instances of classes, which therefore can be thought of as object factories. So in this case, XMLHttpRequest is a built-in object factory (or class), which when we invoke it with the new keyword, returns an object of its type (or an instance of the class XMLHttpRequest).

If you're still a bit confused about this, think of how we created our peleg object earlier. Another way for us to create that object is this:

var peleg = new Object();

And to make sure I wasn't lying about this whole bit, you can make use of the instanceof operator like this:

var peleg = {};

peleg instanceof Object; // should return true

So in our app, by using the built-in constructor function XMLHttpRequest, our computer knows to construct a special object which has all the properties necessary to make requests and handle their responses.

var xhrObject = new XMLHttpRequest();
typeof xhrObject; // 'object'

will still return the string "object" because it is an object. However,

xhrObject instanceof XMLHttpRequest; // true

will return true as the object we've created is an instance of the class XMLHttpRequest and as you'd expect, it has all the "special" properties needed to make what we call an AJAX request:

typeof xhrObject.open; // 'function'
typeof xhrObject.send; // 'function'

Asynchronous Programming

AJAX, this time, is not referring to the bleach, although it is pronounced the same, but rather it is an acronym for Asynchronous JavaScript and XML. This acronym means absolutely nothing to most people, including myself, but let me (or Google) tell you that all that AJAX is is just a request to a server that's being done asynchronously -- or in the background -- without having to block the computer from executing any other code while it is doing so. This concept of asynchronous programming is huge in JS and you will encounter it in many other areas of the language. I'm not entirely sure why JS is inherently asynchronous, but my assumption is that it has a lot to do with the fact that JS is mainly used in the browser to interact with elements on the page and so since such operations can take a while and are partly not within the control of the JS interpreter, those processes need to not block other processes from taking place while it is waiting for those long operations to complete. This is especially important given that the browser, up until not too long ago, had only one processing thread for each of its tabs. So if our JS blocked the browser while fetching some data from a server, the user wouldn't be able to do anything that's controlled by JS on that page until it was done with the other operation! Not cool.

To better illustrate to you this concept of single-threadedness and how JS is using its asynchronous nature to mitigate the issues that arise from that, let's think of it as one person who has only one hand. That person can only do one thing at a time with their one hand. Let's say said person wants to take a sip of some coffee. Well in that case their hand will be occupied holding the coffee mug and so they could not, perhaps, shake their friend's hand while doing so. That's kinda what it means that JS is single-threaded -- it can only do one thing at a time. However, sometimes our one-handed person is relying on other people, or external processes, to execute some action. In our coffee example, such externalities could be a barista making the coffee. While the coffee is being made, our person does not need to wait and be holding the empty cup of coffee. While the coffee is being prepared for our one-handed man, he can put his cup down, shake his friend's hand, and when the coffee is ready, be notified by the barista and only then pick up the cup again. That's kind of what asynchronous means in computer-land.

The barista making our friend's coffee from the previous example could be analogous to what we call in computer-land IO operation. IO means Input/Output and is simply referring to the communication done between our computer and the outside world. An input device, for example could be considered your keyboard, and an output device would be your screen. When your computer needs to rely on such IO devices to do some operations which are somewhat unpredictable and could take a while, it is best for it to not block execution of other code while waiting since it doesn't know when they will be finished. This introduces plenty of issues since our code, therefore, can not be written in a linear manner anymore, and if some code is relying on the result of some IO operation, it will need to be executed only when that IO operation is complete. And that's when we use callbacks; we execute them only when an asynchronous operation is complete and they have all the data they need.

I know this is somewhat high-level thinking and it's probably still hard for you to wrap your head around this topic, but I promise that with time it is going to get easier and clearer. Most languages are not so asynchronous in nature since they are not used in the browser, but we're stuck with JS, so it's important that we cover this concept. "Then why the hell are we starting with JS?!", you're probably asking yourself now. Well, my friend, because JS is one of the most common languages out there. Also, if you start thinking about programming in an asynchronous manner, it will make you a better programmer, IMO. So don't hate. I'm doing you a favor.

Moreover, since JS is basically the only language that can run in your browser, it is growing in popularity by the minute. This means tech giants like Google take interest in it and make it even better! So now everything is on the web! Or the web can do most of the things that we needed native applications for until very recently. We can build iPhone apps with JS. Code editors are written in JS. Even web servers are written in JS. It's definitely a good language to know. And mastering it and its asynchronous nature will make it easier for you to understand code written in other languages as well.

Either way, if our one-handed-coffee-drinking man example was not clear enough, we are soon enough going to see how this whole bit happens in practice, sit tight.

Back to the codez:

var xhrObject = new XMLHttpRequest();

If you inspect the variable xhrObject, by simply typing it again in your Console and hitting Enter, you will see some of the properties and methods available for you inside of it.

The next line in our makeRequest function is responsible for setting up our request object with the arguments necessary via the method open:

xhrObject.open('GET', url, true);

Methods and functions are basically the same only that functions are called methods when they are part of an object. In this case open is a method since it's a property of our object xhrObject, but it is still invoked like any other function. Well it's still a function, only that it has access to its parent object (xhrObject) and therefore it can mutate its data and properties via a special reference to it via the this keyword which luckily for you we're not going to cover in this book.

So we invoke the open method of xhrObject, and we pass it three arguments, the first one is the request verb. This is just a fancy term for what kind of request we are going to use. The most common one is a GET request and it means our request has no body and all of our data is passed to the server via the URL itself. So from our previous example, when our URL looked like this:

http://api.openweathermap.org/data/2.5/weather
  ?appid=fa32f&units=imperial&lon=30&lat=10

it was just passing our three different parameters via the URL to the server. The server then looked for the data and returned to us with a response.

Another common request verb is POST and the main differentiator between it and the GET verb is that it can include a body. If we were to POST our data to the Open Weather Map API (instead of using GET), we would do something similar to the following. Keep in mind this is just speculation and I don't know if the Open Weather Map API accepts POST requests for simple weather data.

Theoretically, our request URL could be just this with a POST:

http://api.openweathermap.org/data/2.5/weather

Note how the URL does not include the query parameters (lon, lat, and units) anymore. So we would have to pass our data in the body of the request itself. The browser's native behavior is to send HTML forms' data directly in the body when using a POST, but in our case, since we're setting up the request manually via the XMLHttpRequest class, we can pass the body as a string to the send method we're going to talk about later. Our request body could be identical to what we previously sent in the URL parameters and might look like this string:

"appid=fa32f&units=imperial&lon=30&lat=10"

Using a POST request with a body like we do here would allow us to provide more data than our GET request allows since URLs are limited in length. More often than not, however, POST requests are reserved for requests that are intended to make some changes to data and have side effects. For example when we submit a form on a site, our data most times is transferred via the body of a POST request and is intended to create or modify a record in a database the server has access to. But this is just a convention most choose to adhere to. Theoretically, a GET request could provide the same effects.

Back to our code. Stop distracting me.

The second argument we're passing to the open method of our XMLHttpRequest object is the URL we're about to make the request with, which includes the query parameters necessary for the Open Weather Map API to know what data to return to us like we illustrated above.

The third parameter we're passing to open is a boolean, with the value of true Now, I initially had no idea why we normally use the boolean true as the third parameter here, but if you look at the Web API Documentation from our friends at the Mozilla Dev Network you'll see that the third argument the open method takes is simply whether our request should be done asynchronously or not. We definitely want it to be async so it doesn't fuck with other browser functionality while it's waiting for the Open Weather Map API to respond. Who knows, they might be busy and take long to gather our data and therefore we opt for setting it to run asynchronously via the true parameter. Yup.

We've drifted for a while, so again, here is our makeRequest function as initially defined in our app:

function makeRequest(url, callback) {
  var xhrObject = new XMLHttpRequest();
  xhrObject.onload = function () {
    var parsedResponse = JSON.parse(xhrObject.responseText)
    callback(parsedResponse);
  };
  xhrObject.open('GET', url, true);
  xhrObject.send();
}

So now let's go back to our asynchronous jungle. After you initialize xhrObject with a new instance of XMLHttpRequest like this:

var xhrObject = new XMLHttpRequest();

Be a doll and type the following in your Console and then hit Enter:

xhrObject.onload;

What did it return? undefined? Well, now we're going to talk a bit about callbacks. Callbacks are something that you'll see used often in JS and it is the language's way to mitigate the issues that arise from its asynchronous nature.

Basically, a callback is just a function. This function is passed as an argument to another function at invocation time so it -- the callback -- can be invoked by the parent function at a later time. Now if you used this description with me when I first learned JS, I would probably start crying.

But seriously, lemme give it another shot.

Remember our call to makeRequest from within getWeather?

function getWeather(coordinate, callback) {

  // some code ...

  makeRequest(url, callback);
}

In the variable callback we already had a function from when getWeather was invoked. If you look ahead to when we invoke getWeather you can see that its callback expects to receive just one argument called weatherData. Just believe me for now if you can't find where it happens.

However, the data we receive from the Open Weather Map API is returned as a plain string, but we need an object. To make sure our callback gets exactly what it needs, we wrap it in another function which converts our response text into a valid JS object using the built-in JSON method, parse, and only then invokes the initial callback.

Again, we're not adding all of this complexity for nothing. Since we don't wanna block our browser and prevent it from doing other tasks on the page while the request is in progress, we have to make use of callbacks. We'll talk more callbacks soon. Keep reading.

But, "Why does a request take time, anyway?" you ask. Well think of it this way, while you were kind enough to hit a couple of keys to initiate a request, your computer had to get its shit together, form the request for you, wait to get an available network connection from the operating system (OS), send the packets (blocks of bytes) over the air to your router, then your router needed to send it to your ISP (Internet Service Provider which is Comcast/Verizon/Time Warner -- whichever one is your thief of choice) via cables (that basically span across the entire world), then they send the request to the destination server which could be placed on the other side of the planet (whatever that means), and then all of this needs to happen again from the other side of the server when it sends you the response (after it's done preparing it for you). AND on top of it all you complain when your computer wants to do more work while waiting for the request? Well, you ungrateful brat, I don't see you travel across continents at the speed of light (or two-thirds of it). But seriously now, my explanation barely even scratches the surface when it comes to describing what happens when your computer sends a request... If you're still curious you should check out this phenomenal attempt at describing the process in more detail.

So with our XHR request, since it's done asynchronously using AJAX, we don't know exactly when it will be done and ready with our result, but our application is kinda dependent on it -- we need that weather data before we can continue. So now our xhrObject has a special property called onload which is initially empty as you've seen, but in our case, we're going to fill it with our callback function that we've passed in to makeRequest earlier. So when our request to the server is complete (we've got the response data), then (and only then) we want our callback function to be called. And this achieves it:

xhrObject.onload = function () {
  callback(xhrObject.responseText);
};

To confuse you even more, we wrap this callback in one more function, called event handler and store it in the onload property of our xhrObject. This event handler, by default, will be called when the load event takes place which signifies the request has finished. Our handler, as you can see, finally invokes callback with our xhrObject's responseText property which should now be populated with the response data.

Keep in mind callback in the example above holds the function we declared when invoking makeRequest and it looks like this:

function (responseText) {
  response = JSON.parse(responseText);
  callback(response);
}

The callback the above function invokes is finally the callback we initially passed in to getWeather.

So back to makeRequest, now it has all we need: we set its destination URL, the HTTP request verb (GET), and lastly, the code we want it to execute when it's complete (the onload callback). So let's set it free and push it to the vast ocean that is the Internets like this:

xhrObject.send();

Where send, as you've probably guessed by now, is yet another method in our xhrObject object.

Capiche?

If this makes sense to you, give yourself a pat on the back, pour yourself some whiskey, and go watch an episode of whatever the latest craze is on Netflix. Otherwise, if this just got you more confused, go get some sleep. Read this again tomorrow when your thinking isn't so murky anymore. I still love you.

Table of Contents
Home