这是Ajax系列的最后一篇。
ECMAScript 5发布有段时间了,其中就包括了解析JSON的原生API-JSON.parse。许多浏览器已经支持了。主流JS库如JQuery,Ext,Prototype都优先使用JSON.parse,不支持该方法的浏览器则使用new Function或eval。 为何优先使用JSON.parse,我想一个就是性能,原生的总是要快一些吧。此外JSON.parse较eval也更安全。
这里也当然不能落后了,优先使用JSON.parse,不行再用new Function方式。最后失败了会给failure的第二个参数msg赋值为"parse json error"
result = function(str){
try{
return JSON.parse(str);
}catch(e){
try{
return (new Function('return ' + str))();
}catch(e){
failure(xhr,'parse json error',e);
}
}
}(xhr.responseText);
完整源码
Ajax =
function(){
function request(url,opt){
function fn(){}
opt = opt || {};
var async = opt.async !== false,
method = opt.method || 'GET',
type = opt.type || 'text',
encode = opt.encode || 'UTF-8',
timeout = opt.timeout || 0,
data = opt.data || null,
success = opt.success || fn,
failure = opt.failure || fn;
method = method.toUpperCase();
if(data && typeof data == 'object'){//对象转换成字符串键值对
data = _serialize(data);
}
if(method == 'GET' && data){
url += (url.indexOf('?') == -1 ? '?' : '&') + data;
data = null;
}
var xhr = function(){
try{
return new XMLHttpRequest();
}catch(e){
try{
return new ActiveXObject('Msxml2.XMLHTTP');
}catch(e){
try{
return new ActiveXObject('Microsoft.XMLHTTP');
}catch(e){
failure(null,'create xhr failed',e);
}
}
}
}();
if(!xhr){return;}
var isTimeout = false, timer;
if(async && timeout>0){
timer = setTimeout(function(){
xhr.abort();
isTimeout = true;
},timeout);
}
xhr.onreadystatechange = function(){
if (xhr.readyState == 4 && !isTimeout){
_onStateChange(xhr, type, success, failure);
clearTimeout(timer);
}else{}
};
xhr.open(method,url,async);
if(method == 'POST'){
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded;charset=' + encode);
}
xhr.send(data);
return xhr;
}
function _serialize(obj){
var a = [];
for(var k in obj){
var val = obj[k];
if(val.constructor == Array){
for(var i=0,len=val.length;i<len;i++){
a.push(k + '=' + encodeURIComponent(val[i]));
}
}else{
a.push(k + '=' + encodeURIComponent(val));
}
}
return a.join('&');
}
function _onStateChange(xhr,type,success,failure){
var s = xhr.status, result;
if(s>= 200 && s < 300){
switch(type){
case 'text':
result = xhr.responseText;
break;
case 'json':
// http://snandy.javaeye.com/blog/615216
result = function(str){
try{
return JSON.parse(str);
}catch(e){
try{
return (new Function('return ' + str))();
}catch(e){
failure(xhr,'parse json error',e);
}
}
}(xhr.responseText);
break;
case 'xml':
result = xhr.responseXML;
break;
}
// text, 返回空字符时执行success
// json, 返回空对象{}时执行suceess,但解析json失败,函数没有返回值时默认返回undefined
typeof result !== 'undefined' && success(result);
//请求超时,调用abort后xhr.status为0,但不知为0时是否还有其它的情况
}else if(s===0){
failure(xhr,'request timeout');
}else{
failure(xhr,xhr.status);
}
xhr = null;
}
return (function(){
var Ajax = {request:request}, types = ['text','json','xml'];
for(var i=0,len=types.length;i<len;i++){
Ajax[types[i]] = function(i){
return function(url,opt){
opt = opt || {};
opt.type = types[i];
return request(url,opt);
}
}(i);
}
return Ajax;
})();
}();
相关: