Page 1 of 4 An Ajax request is a two-way interaction. Some data is sent to the server and the server sends some data back to the client. In this chapter we look at the problems of sending data to the client from the server using the low level Ajax method.
Just jQuery Events, Async & AJAX
Is now available as a print book: Amazon
Contents
- Events, Async & Ajax (Book Only)
- Reinventing Events
- Working With Events
- Asynchronous Code
- Consuming Promises
- Using Promises
- WebWorkers
- Ajax the Basics - get
- Ajax the Basics - post
- Ajax - Advanced Ajax To The Server
- Ajax - Advanced Ajax To The Client
- Ajax - Advanced Ajax Transports And JSONP
- Ajax - Advanced Ajax The jsXHR Object
- Ajax - Advanced Ajax Character Coding And Encoding
Also Available:
buy from Amazon
Advanced Attributes
All HTTP requests return data from the server. The Get and the Post method are designed originally to return an HTML page from the server for the client to display. Of course the whole point of using Ajax is that the "page" that the server returns doesn't have to be displayed and can be processed as general data in any way that the client sees fit. The only problem is that there are a lot of built in data transformations and types that are designed to be useful and make life easier for you but they can some times get between you and the data.
Response data options
There are a set of options that modify the way that data received from the server is processed before being returned to your function.
First recall that there is no option that accepts data from the server like the one that specifies data to be transmitted to the server. As the data sent from the server is received asynchronously, the return data is passed into a callback as a parameter.
The two key parameters that control, or rather try to control, the server's response are dataType and accepts. While these seem simple enough when you first encounter them, they are not as simple as they initially appear. In fact they work together in a way that really isn't well explained in the documentation.
-
accepts
the type of data the client wants back from the server as indicated in the Accept request header.
-
dataType
the type of data the client expects back from the server - a selection of xml, html, script, json, jsonp or text.
You can immediately see that these two options seem to control the same thing - the type of the data returned by the server. In fact they work together on the problem.
If you don't set a dataType then jQuery sends a default Accept header:
Accept:*/*
which means "send me anything".
When the data arrives from the server jQuery attempts to work out what it is based on the MIME type specified in the Content-Type header returned by the server.
If you set a dataType and don't set accepts then jQuery will send a suitable Accept header. For example if you set dataType to html using:
options.dataType="html";
then the Accept header changes to:
Accept: text/html, */*; q=0.01
The q parameter indicates the preference for the */* type. i.e. "you can send me anything other than html but I really don't like it". Without the q or relative quality parameter defaults to 1 and the server might send nothing at all.
If you want some other form of the Accept header you can make use of the accepts option to partially override the default. You can only partially override the default because no matter what you specify you always get "*/*;q=0.01" appended to the end.
The accepts option has to be set to an object of key value pairs. The keys are the datatypes and the values are the replacement data types to put into the accept header.
For example:
options.accepts={html: "text/html;q=0.9", xml: "application/xml;q=0.1"};
sets the header to:
Accept: text/html;q=0.9, */*; q=0.01
if the dataType is set to "html".
Notice that if the dataType is set to a space-separated set of types only the frist type changes the Accept header.
For example:
dataType="html xml";
will only set the Accept header using the html entry in accepts.
That is the header will be:
Accept: text/html;q=0.9, */*; q=0.01
The dataType and the server
The idea of setting the dataType that you expect or require depending on how you look at it is a bit strange. In most HTTP requests that dataType or MIME type to be exact is determined by the file retrieved by the server. An html file has a MIME type of text/html if you request a png file then the type is image/png. The data is retrieved by the server and the appropriate headers are generated to give the client the information it needs to identify and in some cases process the data.
The question that we have to answer is how does a server side program, a PHP program for example, generate a response with a specific type?
The key idea is that the program has to generate the appropriate headers for the type of data it is sending to the client.
For example suppose we want to send some xml data to the client then the PHP program has to send a Content-Type header using the header instruction. The only difficulty with this is that the header instruction has to be the very first in the program because it has to be before the server has started to generate its default headers. In a PHP program any blank lines are sent to the client as part of an HTMl page so the header instruction really does have to be at the very start of the file. To send some XML data you would use something like:
<?php header("Content-Type: application/xml"); $cdata='<?xml version="1.0" encoding="UTF-8"?>'; $cdata.="<Books>"; $cdata.="<Title>Life of Pi</Title>"; $cdata.="<Author>Yann Martel</Author >"; $cdata.="</Books>"; echo($cdata); ?>
and the <?php tag has to be the first in the file.
The jQuery to get this data can be something like:
var options={}; options.url="process.php"; options.method="post"; options.dataType="xml";
$.ajax(options).then( function(data){ console.log(data); });
Setting the dataType to xml and/or setting accept to send a custom header to the server really doesn't make a lot of difference as the MIME type sent by the server is enough to make jQuery process the data returned as XML. In fact if you do set the dataType option to "xml" then the server doesn't need to send the correct MIME type in the header and things work in the same way.
The key point is that in this case jQuery takes the raw data sent by the server and converts it into an XML object. That is in the callback data is no longer a string but an XML object created by calling jQuery.parseXML on the raw data. You can make use of this method to convert your own valid XML strings into an XML object. To work with the XML object you need to look its details up in the XML DOM documentation.
For example to get the textnode corresponding to Title you would have to use:
$.ajax(options).then( function(data){ var nodelist=data.getElementsByTagName('Title'); var textnode=nodelist[0].childNodes[0]; console.log(textnode.nodeValue); });
Notice the XML DOM and node object is provided by the browser and not by jQuery. The jQuery.parseXML makes use of the browser's built in XML facilities.
Working with an XML DOM object isn't as easy as working with jQuery but you can convert it to a jQuery object. For example:
$.ajax(options).then( function(data){ var xml=$(data); console.log(xml.find("Title").text()); console.log(xml.find("Author").text()); });
Note: if you try this in Firefox you might see a soft error "not well-formed". This is a bug and currently being fixed. You can ignore it.
|