Tools New features in jQuery 3 Lead image: Lead Image © Marc Dietrich, 123RF.com
Lead Image © Marc Dietrich, 123RF.com
 

New features in jQuery 3

III

The functions and objects of the jQuery JavaScript library make the work of web developers much easier. Although jQuery 3 remains largely compatible with version 2, some changes might prevent its use. By Tim Schürmann

Using the JavaScript library jQuery [1], developers can access elements of a web page, manipulate them, handle events conveniently, and communicate with the server via Ajax with very little effort. In this way, jQuery helps build complex, dynamic web applications. Its wide distribution also helps promote large content management systems (CMSs) like Joomla or WordPress, which provide or even use jQuery themselves. A W3Techs [2] statistic even suggests that jQuery is used on two-thirds of all websites worldwide.

Dismantling

On June 9, 2016, the developers released jQuery version 3.0 [3]; an update followed as early as the beginning of July in the form of version 3.1 [4]. Unlike jQuery 2, the newer version does not include basic modifications to the library. Instead, the new version cuts out a few old habits and changes the behavior of some interfaces. Above all, the developers wanted to make jQuery 3 leaner and faster in response to two commonly cited points of criticism.

First, they have removed a few workarounds for Internet Explorer. Unlike many websites and reports suggest, jQuery 3 officially continues to support Internet Explorer from version 9. Anyone wanting to cut their website on older Microsoft browsers should stick to jQuery 2 or jQuery 1.12 – both version will continue to receive bug fixes.

Up to now it was possible to register event handlers using the methods .load(), .unload(), and .error(). However, these methods have been regarded as deprecated since jQuery 1.8 and are gone for good in jQuery 3. Anyone who wants to register event handlers should now use .on().

The offset() function determines the location of an item on the website. It might work, but it doesn't make much sense for offsetting a window, for which the answer is then something like { top: 0, left: 0 }. In some other situations, jQuery doesn't return meaningful values. In such cases, jQuery 3 throws an exception and no longer silently ignores such "crazy requests" from the programmer.

Gas Pedal

Animations now use the requestAnimationFrame interface provided by the browser, which means not only do they run more smoothly, they are less of a burden to the processor. All current browsers include the requestAnimationFrame API with the exception of Internet Explorer up to version 9 and Android before version 4.4. The jQuery developers have been experimenting with the interface for several years, but keep stumbling on various compatibility issues. They might think they have largely remedied the issues, but the program code might still get out of step if it is dependent on near real-time animations.

jQuery makes work easier with just a few unique (CSS) selectors. For example, $(":visible") supplies all elements that are currently visible on a page. However, evaluating these special selectors takes longer than with native CSS selectors. For example, to determine all visible elements, the worst case scenario is that the browser will need to completely re-render the page. Thanks to Google developer Paul Irish, jQuery now works noticeably faster if such selectors occur frequently in a document.

In the case of :visible, the developers state that jQuery 3 increases speed by a factor of 17. They also warn that, as before, using the special selectors takes up quite a bit of time. Programmers are therefore better off selecting some items with normal CSS selectors and then only applying them to :visible, :hidden, and similar selectors.

New Delays

The greatest changes are with the Deferred objects. They help manage, monitor, and execute multiple asynchronous tasks and, above all, make it easier to communicate with servers via Ajax. In jQuery 3, the jQuery.Deferred objects are compatible with the Promises/A+ specification or the Promises from ECMAScript 2015. The Deferred interface also passes the tests of the Promises/A+ Compliance Test Suite [5].

Under the hood, the Deferred objects behave differently in several situations: If an exception occurs in jQuery 2, it migrates upward until it eventually reaches window.onerror, thus usually stopping the program. jQuery 3 converts the exception into a rejection for such cases and then calls a stored callback function.

Listing 1 illustrates this with a simple example: It creates a Deferred object and then registers a few callback functions using .then(). The code executes the function submitted in the first parameter of .then() if a Deferred object assumes the Resolved status and everything has therefore run smoothly. However, the function submitted in the second parameter of .then() takes effect if the Deferred object assumes the Rejected status.

Listing 1: Deferred Objects in jQuery 3

01 var deferred = $.Deferred();
02
03 deferred.then(function() {
04         console.log("first callback function");
05         throw new Error("error occured");
06 })
07 .then(
08         function() {console.log(
               "second callback function"); },
09         function(e) {console.log(e.message);}
10 );
11
12 deferred.resolve();

If Listing 1 has registered the callback functions, it immediately changes the deferred object to the Resolved status. The callback function thus takes on the work in the first .then() and throws an error immediately. This would have been the end of it in jQuery 2: Only the output first callback function would have appeared on the console. jQuery 3, on the other hand, converts the exception into a rejection, and the program can run again. Because a rejection is present, jQuery calls the callback function stored as the second parameter with the second .then() and assigns the error that was previously thrown to the function. In jQuery 3, the messages shown in Figure 1 appear on the console.

In jQuery 3, exceptions when using Deferred objects no longer cause the program to terminate.
Figure 1: In jQuery 3, exceptions when using Deferred objects no longer cause the program to terminate.

Another new feature is shown in Listing 2: With immediate effect, callback functions define the status of the Deferred object themselves. A return value that does not have a .then() function causes the execution. In jQuery 2, Listing 2 delivers the output Unsuccessful run, whereas in jQuery 3 it is Successful run.

Listing 2: Deferred States Demo

01 var deferred = $.Deferred();
02
03 deferred.then(
04         null,
05         function() { return "run"; }
06 )
07 .then(
08         function(value) { console.log(
               "Successful", value); },
09         function(value) { console.log(
               "Unsuccessful", value); },
10 );
11
12 deferred.reject();

Callbacks now continuously run asynchronously, even if there is a Deferred object is the Resolved status. Figure 2 illustrates this: In jQuery 2, it first outputs Hello World! and then End of program, because these callbacks run synchronously, depending on their binding. It is the opposite in jQuery 3, which executes the callback function asynchronously.

The JavaScript sample code in the Atom editor with a bright theme.
Figure 2: The JavaScript sample code in the Atom editor with a bright theme.

The .then() function behaves differently in several situations in jQuery 3, as well. If you need the old behavior, you need to replace the .then() in your code with the .pipe() method to get the old behavior and the same signature as the .then() method. Promise objects also offer the new .catch() method, which only works as an alias for the .then(zero function).

A new plugin helps when debugging Deferred objects: the jQuery Deferred Reporter [6] provides information on the console that the developers can use to trace the source of their errors.

Point One

Version 3.1, released not even one month after the release of version 3.0, works differently in one case: In version 3.0, the jQuery developers converted jQuery.ready() and jQuery.fn.ready() internally to the new Deferred objects. They therefore also passed onerrors to the Rejection handler internally.

This caused a problem: If programmers supplemented a ready handler in the usual way – that is, with either of

jQuery(function() { ... })
jQuery(document).ready(function() { ... })

they were then unable to register a Deferred handler. Consequently, they learned nothing from an error (silent errors). To make matters worse, before version 3.1 programmers weren't able to identify uniquely whether the new Deferreds were suddenly pottering about under the hood.

jQuery 3.1, on the other hand, reports errors on the console by default. Programmers can control the behavior using the new method jQuery.readyException(). jQuery passes on any errors that occur in a ready handler to this method:

jQuery.readyException = function(error) {
  // each ready handler throws errors
};

To not block the execution of an application, jQuery.readyException() throws the error asynchronously and writes it to the console.

Slimming Cure

The developers have offered a "slim" variant of jQuery since version 3.0. It is missing the Ajax functions, the effects module, and the deprecated code. The minimized version of the slim variant (jQuery-3.1.0.slim.min.js) is about 17KB smaller than the minimized normal jQuery 3 (jQuery-3.1.0.min.js), which still carries plenty of weight at around 84.3KB.

Anyone wanting to upgrade from jQuery 2 to jQuery 3 should definitely read the jQuery Core 3.0 Upgrade Guide [7] beforehand. The jQuery developers also provide a Migrate plugin [8] on GitHub, which on the one hand issues a warning if you access functions that no longer exist in jQuery 3 or are considered deprecated. On the other hand, it simulates the behavior of jQuery 2, thus making it possible to revise web applications gradually.

Anyone who uses a framework such as Bootstrap [9] or a CMS like Joomla [10] needs to investigate which jQuery versions they use, because they often cannot be changed readily.

Conclusions

jQuery 3 is a logical development of version 2. The changes are limited, and the developers have discarded some of the code that has been deprecated for a while. So heaving a web application onto jQuery 3 shouldn't require that much work. However, with the minimized version at almost 85KB, jQuery 3 is still a hefty chunk. The jQuery team is now focused on further developing jQuery 3. However, the old versions 1.12 and 2.2 still receive bug fixes, so developers can address the migration in peace.