Quantcast
Viewing latest article 1
Browse Latest Browse All 276

An Introduction to jQuery’s Deferred Objects

For a long time, JavaScript developers have used callback functions to perform several tasks. A very common example is to add a callback via the addEventListener() function to execute various operations when an event, such as click or keypress, is fired. Callback functions are simple and get the job done for simple cases. Unfortunately, when your web pages increase in complexity and you need to perform many asynchronous operations, either in parallel or in sequence, they become unmanageable.

ECMAScript 2015 (a.k.a. ECMAScript 6) introduced a native means to deal with such situations: promises. If you don’t know what promises are, you can read the article An Overview of JavaScript Promises. jQuery provided and still provides its own flavor of promises, called Deferred objects. They were introduced to jQuery years before promises were introduced to ECMAScript. In this article, I’ll discuss what Deferred objects are, and what problems they try to solve.

[author_more]

A Brief History

The Deferred object was introduced in jQuery 1.5 as a chainable utility used to register multiple callbacks into callback queues, invoke callback queues, and relay the success or failure state of any synchronous or asynchronous function. Since then, it has been the subject of discussion, some criticism, and a lot of changes along the way. A couple of examples of criticism are You’re Missing the Point of Promises and JavaScript Promises and why jQuery implementation is broken.

Together with the Promise object, Deferred represents the jQuery implementation of promises. In jQuery version 1.x and 2.x the Deferred object adheres to the CommonJS Promises/A proposal. This proposal was used as a base for the Promises/A+ proposal which native promises are built upon. As mentioned in the introduction, the reason why jQuery doesn’t adhere to the Promises/A+ proposal is because it implemented promises way before this proposal was even conceived.

Because jQuery was a precursor and due to backward-compatibility issues, there are differences in how you can use promises in pure JavaScript and in jQuery 1.x and 2.x. Moreover, because jQuery follows a different proposal, the library is incompatible with other libraries that implemented Promises such as the Q library.

In the upcoming jQuery 3 the interoperability with native Promises (as implemented in ECMAScript 2015) has been improved. The signature of the main method (then()) is still a bit different for backward compatibility, but the behavior is more in line with the standard.

Callbacks in jQuery

To understand why you might even need the use of the Deferred object, let’s discuss an example. When using jQuery, it’s very common to use its Ajax methods to perform asynchronous requests. For the sake of the example, let’s say that you’re developing a web page that is sending Ajax requests to the GitHub API. Your goal is to retrieve the list of a user’s repositories, find the most recently updated repository, locate the first file with the string “README” in its name and finally retrieve that file’s contents. Based on this description, each Ajax request may only start when the previous step has been completed. In other words, the requests must run in sequence.

Turning the previous description into pseudocode (please note that I’m not using the real GitHub API), we get:

var username = 'testuser';
var fileToSearch = 'README.md';

$.getJSON('https://api.github.com/user/' + username + '/repositories', function(repositories) {
   var lastUpdatedRepository = repositories[0].name;

   $.getJSON('https://api.github.com/user/' + username + '/repository/' + lastUpdatedRepository + '/files', function(files) {
      var README = null;

      for (var i = 0; i < files.length; i++) {
         if (files[i].name.indexOf(fileToSearch) >= 0) {
            README = files[i].path;

            break;
         }
      }

      $.getJSON('https://api.github.com/user/' + username + '/repository/' + lastUpdatedRepository + '/file/' + README + '/content', function(content) {
         console.log('The content of the file is: ' + content);
      });
   });
});

As you can see in this example, using callbacks we have to nest the calls to perform the Ajax requests in the sequence we want. This makes the code less readable. The situation where you have a lot of nested callbacks, or independent callbacks that have to be synchronized, is often referred to as the “callback hell.”

To make it slightly better, you can extract named functions from the anonymous inline functions I created. However, this change doesn’t help much and we still find ourselves in callback hell. Enter the Deferred and the Promise objects.

Continue reading %An Introduction to jQuery’s Deferred Objects%

Article Source jQuery Blog.
Read Full Article An Introduction to jQuery’s Deferred Objects.


Viewing latest article 1
Browse Latest Browse All 276

Trending Articles