# Promises

### Introduction

Asynchronous execution is one of the most fundamental and elementary concepts of JavaScript, yet one which troubles beginner developers both in understanding it and handling it.

The architecture of JavaScript utilizes essentially two things to work around asynchronous operations and track when they complete or fail. They are *events* and *callbacks*.

As we know, an event is simply an action occuring on a webpage while a callback is a function passed to another function as an argument. Both of these ideas are what enable handling asynchronous tasks in the language

For example, when working with `XMLHttpRequest`, we handle events for things such as state changes, abortion, or progress of the request. Similarly, when reading files in JavaScript via the `readfile()` function of the `filesystem` module, in the Node.js runtime environment, we pass a callback to `readfile()`, which is then invoked when the file's reading operation completes.

While they offer superb convenience to developers in writing basic asynchronous code, events and callbacks start to crumble apart in their syntactic structure as soon as the underlying code becomes more complex. With more code, comes less maintainability and more snag.

In this chapter, we aim to unravel the exact problems associated with the callback-style of writing asynchronous code and then see the solution to them in the form of something called *promises*.

### Pitfalls of callbacks

To put up a practical-level discussion on the complications of using callbacks, we would need a real example that uses them, and is itself used a lot. Perhaps the best choice would be AJAX.

AJAX stands for Asynchronous JavaScript and XML, and is a technique of sending out HTTP requests from the browser asynchronously, without requiring a full page reload. It's used extensively by many large web applications - such as Facebook, Google etc. - to add a whole new level of interactivity and modernism to their user interfaces.

For a detailed guide to AJAX please refer to our [AJAX Course](https://www.codeguage.com/courses/ajax/).

Let's consider a very basic AJAX call. Suppose you want to request the `names.txt` file shown below using AJAX:

names.txt

```javascript
Only one file linked for now.
foods.txt
```

The code to do this, will be something like the following:

```javascript
var xhr = new XMLHttpRequest();
xhr.open("GET", "names.txt", true);
xhr.onload = function() {
   if (this.status === 200) {
      document.write(this.responseText);
   }
}
xhr.send();
```

Now although this works well, as soon as the need be to perform nested AJAX requests (one in another) we'll end up with a strenous-to-maintain block of code. An example would be worth the discussion.

Imagine that after successfully requesting the `names.txt` file above, we want to separately request the file mentioned within it i.e `foods.txt`.

foods.txt

```
Pizza
Pasta
Cookies
```

What we'll need to do in order to accomplish this, is to process the response of `names.txt`, extract the filename from it, and then finally request for it with a new AJAX call.

Something like:

```javascript
var xhr = new XMLHttpRequest();
xhr.open("GET", "names.txt", true);
xhr.onload = function() {
   if (this.status === 200) {
      // process the response
      var filename = this.responseText.split("\n")[1]; // extract the filename

      // new AJAX request
      var xhr2 = new XMLHttpRequest();
      xhr2.open("GET", filename, true);

      xhr2.onload = function() {
         if (this.status === 200) {
            alert(this.responseText);
         }
      }
      xhr2.send();
   }
}
xhr.send();
```

Here we're assuming that `names.txt` contains a filename in its second line.

Inside the `onload` handler for the first xhr request to `names.txt` (in line 3), we have the logic laid out for the second xhr request to `foods.txt`, which when completes, calls the `onload` handler in line 12 - where we finally output the content of the `foods.txt` file.

Notice how the indentations are starting to become longer and longer, pushing out sub-level code further to the right. One might argue and say that, we can create a separate function and put all the code for the second AJAX call within it, and thus avoid the indentation - as shown below:

```javascript
function secondRequest(xhr) {
   var filename = xhr.responseText.split("\n")[1];

   var xhr2 = new XMLHttpRequest();
   xhr2.open("GET", filename, true);

   xhr2.onload = function() {
      if (this.status === 200) {
         alert(this.responseText);
      }
   }
   xhr2.send();
}

var xhr = new XMLHttpRequest();
xhr.open("GET", "names.txt", true);
xhr.onload = function() {
   if (this.status === 200) {
      // process the response
      secondRequest(this)
   }
}
xhr.send();
```

Everything is the same here as before, except for that this time the logic for the second xhr request is defined in a function, `secondRequest()`; and not directly.

Even better, someone can come up with the following code - defining just a single function to create a new AJAX request with the given filename and callback (to fire when the request completes successfully):

```javascript
function ajaxRequest(filename, callback) {
   var xhr = new XMLHttpRequest();
   xhr.open("GET", filename, true);
   xhr.callback = callback;
   xhr.onload = function() {
      if (this.status === 200) this.callback();
   }
   xhr.send();
}

ajaxRequest("names.txt", function(e) {
   var filename = this.responseText.split("\n")[1];
   ajaxRequest(filename, function() {
      alert(this.responseText);
   });
});
```

The `callback` property is given to the xhr object (in line 4) in order to invoke it with `this` equal to the `xhr` object.

Good thinking! But this can only suffice until error-handling and further nested AJAX calls aren't required in the code. As soon as either one enters the game, it's simply game over!

Consider the snippet below extending our previous AJAX code with an error-handling logic:

```javascript
function ajaxRequest(filename, callback, errorCallback) {
   var xhr = new XMLHttpRequest();
   xhr.open("GET", filename, true);
   xhr.callback = callback;
   xhr.onload = function() {
      if (this.status === 200) this.callback();
   }
   xhr.onerror = errorCallback;
   xhr.send();
}

ajaxRequest("names.txt", function(e) {
   var filename = this.responseText.split("\n")[1];

   ajaxRequest(filename, function() {
      alert(this.responseText);
   }, function(e) { console.error("Error!") });

}, function(e) { console.error("Error!") });
```

Notice how the `onerror` handler is redefined for no reason whatsoever - the error handling logic is the same i.e to throw an error saying `"Error!"`, however the functions to do this are different!

A simple workaround would be to create a separate error handler function like `handleError()` below, and pass it to the individual `ajaxRequest()` functions:

```javascript
function handleError() {
   console.error("Error!");
}

ajaxRequest("names.txt", function(e) {
   var filename = this.responseText.split("\n")[1];
   ajaxRequest(filename, function() {
      alert(this.responseText);
   }, handleError);
}, handleError);
```

But even then the overall syntax of the code would remain cluttered. Just look at the code above - don't you think it looks *way overwhelming*?

Nonetheless, this is just one of the many problems with the callback syntax - the story doesn't end here.

For a split second imagine that `foods.txt` also requires calling another file such as `pizza.txt`. Then the code will approach what is commonly known as a callback hell:

pizza.txt

```
Chicken Tikka Pizza
BBQ Pizza
Cheese Pizza
```

```javascript
ajaxRequest("names.txt", function(e) {
   var filename = this.responseText.split("\n")[1];
   ajaxRequest(filename, function() {
      var filename = this.responseText.split("\n")[1];
      ajaxRequest(filename, function() {
         alert(this.responseText);
      }, handleError);
   }, handleError);
}, handleError);
```

See how the callbacks are starting to become tangled and pushed continuously rightwards. With a couple of these we would simply end up with a *callback hell*, also known as the *pyramid of doom*:

```javascript
func1(function(data) {
   func2(function(data) {
      func3(function(data) {
         func4(function(data) {
            // some code
         });
      });
   });
});
```

This looks ugly and is, no doubt, difficult to maintain.

Bundle error-handling code into it, and you'll *'put yourself into the real hot waters'*.

However these aren't the only cons in using callbacks - there exist more; ones that definitely need another way to be accomplished. For example, consider the task of requesting multiple files in one go and then executing a function once all of them are fetched completely.

Take your time, and try to think on this problem in the *callback style* for a while; see where you end up!

### Promises step in

Solving all the problems, discussed in the section above, steps in the concept of *promises*. *So what exactly is a promise?*

Defining it in terms of the idea behind it:

A *promise* is a means of simplifying the task of writing complex asynchronous code.

But this ain't the definition that precisely tells us what a promise is — it's, more or less, just a convenient way to look at it.

In more technical terms:

A *promise* is an object that represents the success or failure of a given operation, usually an asynchronous operation.

OK, now this might be *too much to digest* at a time!

In layman terms, a promise is simply a means of *placeholding* the completion or failure of a given task. Usually, this task is an asynchronous task - what promises are really meant for.

Promises aren't meant for synchronous tasks.

*'Placeholding'* means that once the promise executes its given task, it serves to *hold onto* the result which can be a success or a failure.

Using this held-on outcome, the program can then carry out respective actions such as further processing the data in the case of a success or logging an error in the case of a failure.

Don't worry if you couldn't understand a word in this discussion. Promises are verily one of the concepts in JavaScript that don't make any sense at all, unless and until you rigorously experiment with them.

If the definitions go above your head, which they normally should, just ignore them for now. Just stay focused on learning the internal behavior behind promises and you'll soon be writing definitions of your own!

Coming back to the topic, all promise-related utitilies in JavaScript are given under the `Promise` interface. Any promise that we ought to create has to essentially utilize the `Promise` interface in one way or the other, always.

Talking about how to actually create a promise and then work with it, we will discuss the bits and pieces to this in detail in the next [JavaScript Promises](https://www.codeguage.com/courses/advanced-js/promises-basics) chapter.

For the moment let's get a quick overview of what benefits do promises come bundled with.

### Benefits of using promises

First of all promises mitigate the extra levels of indentation, we saw earlier, by a mechanism for *attaching* callbacks instead of *passing* them to another function.

Secondly, error-handling in promises, is a lot more concise and maintainable than error-handling in callbacks. Promises are built upon the conventional `try..catch` model used to respond to thrown exceptions, and thus offers more convenience to developers in writing exception-handling code.

Moreover, the promise syntax relates to English language very closely, consequently making linked asynchronous calls seem way more meaningful and comprehensive to understand. At the heart of this idea lies the `then()` method, as we shall see in the next chapter.

And the story doesn't even end here — it's just that we'll get a bit overwhelmed seeing all the minute pros that promises have to offer us, in one go. It's best to keep things simple for now, leaving the rest of the ideas to be explored one-by-one in the following chapters.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://edrus.gitbook.io/mt-it/2nd-month/week-7/javascript/promises.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
