Skip to content
Permalink
Browse files

Rewrote the data conversion logic in ajax. Should be cleaner and faster.

  • Loading branch information...
jaubourg authored and jaubourg committed Dec 21, 2010
1 parent 4c49c87 commit fef0f63526df8c4e186780c742fbcd717424581b
Showing with 70 additions and 112 deletions.
  1. +2 −7 src/ajax.js
  2. +68 −105 src/xhr.js
@@ -166,11 +166,6 @@ jQuery.extend({
xhr: function() {
return new window.XMLHttpRequest();
},
xhrResponseFields: {
xml: "XML",
text: "Text",
json: "JSON"
},

accepts: {
xml: "application/xml, text/xml",
@@ -195,13 +190,13 @@ jQuery.extend({
// 4) the catchall symbol "*" can be used
// 5) execution will start with transport dataType and THEN continue down to "*" if needed
prefilters: {},

// Transports bindings
// 1) key is the dataType
// 2) the catchall symbol "*" can be used
// 3) selection will start with transport dataType and THEN go to "*" if needed
transports: {},

// Checkers
// 1) key is dataType
// 2) they are called to control successful response
@@ -6,11 +6,9 @@ var rquery_xhr = /\?/,
rnoContent = /^(?:GET|HEAD)$/,
rts = /([?&])_=[^&]*/,
rurl = /^(\w+:)?\/\/([^\/?#]+)/,

sliceFunc = Array.prototype.slice,

isFunction = jQuery.isFunction;


sliceFunc = Array.prototype.slice;

// Creates a jQuery xhr object
jQuery.xhr = function( _native ) {

@@ -86,7 +84,7 @@ jQuery.xhr = function( _native ) {
if ( data && s.processData && typeof data != "string" ) {
data = s.data = jQuery.param( data , s.traditional );
}

// Get internal
internal = jQuery.xhr.prefilter( s ).transport( s );

@@ -147,7 +145,7 @@ jQuery.xhr = function( _native ) {
requestHeaders[ i.toLowerCase() ] = headers[ i ];
}
}

callbackContext = s.context || s;
globalEventContext = s.context ? jQuery(s.context) : jQuery.event;

@@ -223,112 +221,77 @@ jQuery.xhr = function( _native ) {
// Chain data conversions and determine the final value
// (if an exception is thrown in the process, it'll be notified as an error)
try {

function checkData(data) {
if ( data !== undefined ) {
var testFunction = s.dataCheckers[srcDataType];
if ( isFunction( testFunction ) ) {
testFunction(data);
}
}
}

function convertData (data) {
var conversionFunction = dataConverters[srcDataType+" => "+destDataType] ||
dataConverters["* => "+destDataType],
noFunction = ! isFunction( conversionFunction );
if ( noFunction ) {
if ( srcDataType != "text" && destDataType != "text" ) {
// We try to put text inbetween
var first = dataConverters[srcDataType+" => text"] ||
dataConverters["* => text"],
second = dataConverters["text => "+destDataType] ||
dataConverters["* => "+destDataType],
areFunctions = isFunction( first ) && isFunction( second );
if ( areFunctions ) {
conversionFunction = function (data) {
return second( first ( data ) );
};

var i,
current,
prev,
checker,
conv1,
conv2,
oneConv,
convertion,
dataTypes = s.dataTypes,
dataCheckers = s.dataCheckers,
dataConverters = s.dataConverters,
dataFilter = s.dataFilter,
responses = {
"xml": "XML",
"text": "Text"
};

for( i = 0 ; i < dataTypes.length ; i++ ) {

current = dataTypes[ i ];

if ( i ) {

prev = dataTypes[ i - 1 ];

if ( prev === "*" ) {

prev = current;

} else if ( current !== "*" && prev !== current ) {

oneConv = conv1 =
dataConverters[ ( conversion = prev + " => " + current ) ] ||
dataConverters[ "* => " + current ];

if ( ! oneConv && prev !== "text" && current !== "text" ) {
conv1 = dataConverters[ prev + " => text" ] || dataConverters[ "* => text" ];
conv2 = dataConverters[ "text => " + current ];
}
if ( oneConv || conv1 && conv2 ) {
response = oneConv ? conv1( response ) : conv2( conv1( response ) );
} else {
throw "no " + conversion;
}
noFunction = ! areFunctions;
}
if ( noFunction ) {
jQuery.error( "no data converter between " + srcDataType + " and " + destDataType );
}

}
return conversionFunction(data);
}

var dataTypes = s.dataTypes,
i,
length,
data = response,
dataConverters = s.dataConverters,
srcDataType,
destDataType,
responseTypes = s.xhrResponseFields;

for ( i = 0, length = dataTypes.length ; i < length ; i++ ) {

destDataType = dataTypes[i];

if ( !srcDataType ) { // First time

// Copy type
srcDataType = destDataType;
// Check
checkData(data);
// Apply dataFilter
if ( isFunction( s.dataFilter ) ) {
data = s.dataFilter(data, s.dataType);
// Recheck data
checkData(data);
}

} else { // Subsequent times

// handle auto
// JULIAN: for reasons unknown to me === doesn't work here
if (destDataType == "*") {

destDataType = srcDataType;

} else if ( srcDataType != destDataType ) {

// Convert
data = convertData(data);
// Copy type & check
srcDataType = destDataType;
checkData(data);

}


checker = dataCheckers[ current ];

if ( response != null && checker ) {
checker( response );
}

// Copy response into the xhr if it hasn't been already
var responseDataType,
responseType = responseTypes[srcDataType];

if ( responseType ) {

responseDataType = srcDataType;

} else {

responseType = responseTypes[ responseDataType = "text" ];


if ( responses[ current ] ) {
xhr[ "response" + responses[ current ] ] = response;
responses[ current ] = 0;
}

if ( responseType !== 1 ) {
xhr[ "response" + responseType ] = data;
responseTypes[ responseType ] = 1;

if ( ! i && dataFilter ) {

response = dataFilter( response );

dataTypes = s.dataTypes;
dataFilter = 0;
i--;
}

}

// We have a real success
success = data;
success = response;
isSuccess = 1;

} catch(e) {
@@ -406,7 +369,7 @@ jQuery.xhr = function( _native ) {
// Ready state change
function setState( value ) {
xhr.readyState = value;
if ( isFunction( xhr.onreadystatechange ) ) {
if ( jQuery.isFunction( xhr.onreadystatechange ) ) {
xhr.onreadystatechange();
}
}

0 comments on commit fef0f63

Please sign in to comment.
You can’t perform that action at this time.