Getting Started With jQuery - Advanced Ajax Transports
Written by Ian Elliot   
Monday, 09 November 2015
Article Index
Getting Started With jQuery - Advanced Ajax Transports
JSONP
Custom prefilter

One of the interesting things about jQuery's approach to Ajax is that it can be extended in many ways. In the previous chapter we discovered that you can use converters to create your own data types, but jQuery lets you go much further - you can create your own custom transport types.  

Just jQuery
Events, Async & AJAX

Is now available as a print book: Amazon 

jquery2cover

 

Contents

  1. Events, Async & Ajax (Book Only)
  2. Reinventing Events
  3. Working With Events
  4. Asynchronous Code
  5. Consuming Promises
  6. Using Promises 
  7. WebWorkers
  8. Ajax the Basics - get
  9. Ajax the Basics -  post
  10. Ajax - Advanced Ajax To The Server
  11. Ajax - Advanced Ajax To The Client
  12. Ajax - Advanced Ajax Transports And JSONP
  13. Ajax - Advanced Ajax The jsXHR Object
  14. Ajax - Advanced Ajax Character Coding And Encoding 

Also Available:

buy from Amazon

smallcoverjQuery

 

Advanced Attributes

 

Ajax was originally about getting data into a web page without reloading the page using the built-in XMLHttpRequest object that all browsers support. This is generally what is meant when a programmer says that they are using Ajax, but there are other ways of getting data to and from the server and jQuery attempts to unify all of these ways in a single approach.

The most common alternative transport types provided as standard by jQuery are JSONP and cross domain script. These data types are implemented using a script tag transport, but as they are presented in the same way as the other data types in jQuery Ajax this fact is often overlooked. Let's find out how it works.

Working with script transport

As explained in the previous chapter, when you make a script Ajax request to the same domain as the page was loaded from the standard Ajax XMLHttpRequest transport is used. The text that is returned is converted to script using the built in data type converter:

options.contents={script: /(?:java|ecma)script/}
options.converters={"text script":
   function( text ) {
    jQuery.globalEval( text );
    return text;
   }}

Notice that this causes the script to be evaluated and the text returned for further processing. The advantage of using the XMLHttpRequest transport is that all of the status indicators, events and errors are generated automatically.

However, the  XMLHttpRequest transport doesn't work with a cross domain request (without the help of CORS). If you make a cross domain script request then jQuery switches to a different transport that does work across domains. 

A  cross domain script request is quite different from the majority of jQuery Ajax requests. It isn't implemented using the built-in XMLHttpRequest object. Instead the request is made by dynamically adding a <script> tag to the DOM with the URL of the requested script. Doing this automatically starts browser downloading the script and then executing it when loaded. 

For example, when you make a request for a script data type what jQuery actually does is:

script = document.createElement('script');
script.type = 'text/javascript'; 
script.src = 'http://myScript.js';

As soon as the src property is set the browser starts to download the specified script. When the script has been downloaded it is added to the script DOM element and executed. 

There are differences in the two types of transport. For example the only error that you will get is a time out and there is no returned raw data for a script transport. 

You can force jQuery to use a cross domain transport using the crossDomain option;

crossDomain

If you want jQuery to treat a request a cross domain even when it isn't you can set crossDomain to true. This will result in any cross domain alternative transport to be used in place of the XMLHttpRequest transport.

For example if you want to make a cross domain script request to the same domain that the page was served from you could use:

var options={};
options.url="process.php";
options.method="get";
options.dataType="script";
options.crossDomain=true;
$.ajax(options).then(
 function(data){
  console.log(data);
 });

In this case the script will be loaded and executed and the done method will be called but data will be undefined. 

Working with JSONP transport

JSONP is a variant of Script transport. It sends JSON formatted data but wrapped by a function call which is executed to process the data. The function is supplied by the client.  

So put simply a JSONP request is a script request where the script has the standard format:

wrapperFunction(JSON);

As in the case of a script request which transport is used depends on whether the domain of the request is the same as the page or different. 

If the request is to the same domain then the  XMLHttpRequest transport is used and the same basic data conversions are used as for script. That is the JSONP is downloaded as text and then converted to script and executed. 

If you make a cross domain JSONP request, or indeed a cross domain JSON request the jQuery automatically switches to using the script transport.  There are a few differences but in the main you can assume that JSONP works in roughly the same way no matter what the transport is and this isn't quite the same as jQuery Ajax in the case of other data types. 

Why would we bother to implement JSON data transfer in this round about way?

Why not just use JSON? 

The simple answer is that an XMLHttpRequest cannot be to anything other than the domain the page making the request loaded from unless you make use of CORs - see later. A script based transport on the other hand can work cross domain by default. By wrapping the JSON data in a function call we convert the data into a script that can be executed and hence something that can make use of script transport for cross domain requests.

That is you can use JSONP to retrieve JSON data from any server that supports it without the problem of the same domain policy.

That is there are a few additional mechanisms that relate to the wrapper function that you need to know about to make use of JSONP. 

As already explained if you make a JSONP request the code is downloaded and run. By convention this code is usually a single function which is passed the JSON string:

myFunction(jsonData);

When this is loaded and executed then myFunction is run on the client and as already explained myFunction is provided by the client and not as part of the JSONP code. 

This provides a callback mechanism in that you can define myFunction to process the jsonData in anyway that you like and the calling of myFunction indicates that the JSONP request has been completed i.e. the JSON data is ready to work with. 

Of course the client and the server have to agree on the name of the function to be used and this makes the protocol just a little more complicated.

The way that JSONP is implemented introduces some differences in the general Ajax handling that go beyond just a simple change in transport.  

The first big difference is that jQuery cannot effectively work with JSONP unless you explicitly tell it that you are making a JSONP request because it needs to set things up correctly before the request is made. That is for the JSONP script tag mechanism to be used you have to set dataType to jsonp.

The second big difference is that unless you play by some additional rules you will not be able to make use of the Promise based callbacks or indeed any of the usual Ajax callbacks. The reason is that to make JSONP look like a standard Ajax request jQuery maps the function that wraps the JSON data to the success method of the Promise object. 

It is instructive to first see how this all works if you don't play by these additional rules.

Let's make a very simple "raw" JSONP request:

var options={};
options.url="process.php";
options.method="get";
options.dataType="jsonp";
$.ajax(options).done(
 function(data){
  console.log(data);
 });

Even at this basic level there is already a new "rule" in operation - you have to use a Get and not a Post. The reason is that jQuery adds some data to the Get URL that we will have to make use of later. 

 

justjquery

 



Last Updated ( Thursday, 05 May 2022 )