源文见: http://api.jquery.com/extending-ajax/
相比之前的版本, 重写了ajax模块, 引入更多的扩展点. 三个概念:
Prefilters
A prefilter is a callback function that is called before each request is sent, and prior to any $.ajax() option handling.
Prefilters are registered using $.ajaxPrefilter(), and a typical registration looks like this:
$.ajaxPrefilter( function( options, originalOptions, jqXHR ) { // Modify options, control originalOptions, store jqXHR, etc });
- options are the request options
- originalOptions are the options as provided to the ajax method, unmodified and, thus, without defaults from ajaxSettings
- jqXHR is the jqXHR object of the request
It is also possible to attach a prefilter to requests with a specific dataType. For example, the following applies the given prefilter to JSON and script requests only:
$.ajaxPrefilter( "json script", function( options, originalOptions, jqXHR ) { // Modify options, control originalOptions, store jqXHR, etc });
Converters (注册自己的数据转换处理)
A converter is a callback function that is called when a response of a certain dataType is received while another dataType is expected.
Converters are stored into ajaxSettings and can be added globally as follows:
$.ajaxSetup({ converters: { "text mydatatype": function( textValue ) { if ( valid( textValue ) ) { // Some parsing logic here return mydatatypeValue; } else { // This will notify a parsererror for current request throw exceptionObject; } } } });
Converters are useful to introduce custom dataTypes. They can also be used to transform data into desired formats. Note: all custom dataTypes must be lowercase.
With the example above, it is now possible to request data of type "mydatatype" as follows:
$.ajax( url, { dataType: "mydatatype" });
或者也可以直接写在ajax单独的一次处理里
$.ajax( url, { dataType: "xml text mydatatype", converters: { "xml text": function( xmlValue ) { // Extract relevant text from the xml document return textValue; } } });
Transports (自定义整个的传输过程, 这是迫不得已才用)
A transport is an object that provides two methods, send and abort, that are used internally by $.ajax() to issue requests. A transport is the most advanced way to enhance $.ajax() and should be used only as a last resort when prefilters and converters are insufficient.
Since each request requires its own transport object instance, tranports cannot be registered directly. Therefore, you should provide a function that returns a transport instead.
Transports factories are registered using $.ajaxTransport(). A typical registration looks like this:
$.ajaxTransport( function( options, originalOptions, jqXHR ) { if( /* transportCanHandleRequest */ ) { return { send: function( headers, completeCallback ) { /* send code */ }, abort: function() { /* abort code */ } }; } });
- options are the request options
- originalOptions are the options as provided to the ajax method, unmodified and, thus, without defaults from ajaxSettings
- jqXHR is the jqXHR object of the request
- headers is a map of request headers (key/value) that the transport can transmit if it supports it
- completeCallback is the callback used to notify ajax of the completion of the request
completeCallback has the following signature:
function( status, statusText, responses, headers ) {}
- status is the HTTP status code of the response, like 200 for a typical success, or 404 for when the resource is not found.
- statusText is the statusText of the response.
- responses (Optional 可选) is a map of dataType/value that contains the response in all the formats the transport could provide (for instance, a native XMLHttpRequest object would set reponses to { xml: XMLData, text: textData } for a response that is an XML document)
- headers (Optional) is a string containing all the response headers if the transport has access to them (akin to what XMLHttpRequest.getAllResponseHeaders() would provide).
Just like prefilters, a transport's factory function can be attached to specific dataType:
$.ajaxTransport( "script", function( options, originalOptions, jqXHR ) { /* Will only be called for script requests */ });
The following example shows how a minimal image transport could be implemented:
$.ajaxTransport( "image", function( s ) { if ( s.type === "GET" && s.async ) { var image; return { send: function( _ , callback ) { image = new Image(); function done( status ) { if ( image ) { var statusText = ( status == 200 ) ? "success" : "error", tmp = image; image = image.onreadystatechange = image.onerror = image.onload = null; callback( status, statusText, { image: tmp } ); } } image.onreadystatechange = image.onload = function() { done( 200 ); }; image.onerror = function() { done( 404 ); }; image.src = s.url; }, abort: function() { if ( image ) { image = image.onreadystatechange = image.onerror = image.onload = null; } } }; } });
Handling Custom Data Types
在jquery源码里, 已定义了几种处理类型
The jQuery Ajax implementation comes with a set of standard dataTypes, such as text, json, xml, and html.
Use the converters option in $.ajaxSetup() to augment or modify the data type conversion strategies used by $.ajax().
The unminified jQuery source itself includes a list of default converters, which effectively illustrates how they can be used:
// List of data converters // 1) key format is "source_type destination_type" // (a single space in-between) // 2) the catchall symbol "*" can be used for source_type converters: { // Convert anything to text "* text": window.String, // Text to html (true = no transformation) "text html": true, // Evaluate text as a json expression "text json": jQuery.parseJSON, // Parse text as xml "text xml": jQuery.parseXML }
When you specify a converters option globally in $.ajaxSetup() or per call in $.ajax(), the object will map onto the default converters, overwriting those you specify and leaving the others intact.
For example, the jQuery source uses $.ajaxSetup() to add a converter for "text script":
jQuery.ajaxSetup({ accepts: { script: "text/javascript, application/javascript" }, contents: { script: /javascript/ }, converters: { "text script": jQuery.globalEval } });