新API解析JSONAjax之七

这是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;
	})();
}();

相关:

ajax_07.zip

https://github.com/snandy/io

原文地址:https://www.cnblogs.com/snandy/p/2026742.html