Ajax实战(7):新API解析JSON
这是我们实战系列的最后一篇。
ECMAScript 5发布有段时间了,其中就包括了解析ON的原生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"
01 result = function(str){
02 try{
03 return JSON.parse(str);
04 }catch(e){
05 try{
06 return (new Function('return ' + str))();
07 }catch(e){
08 failure(xhr,'parse json error',e);
09 }
10 }
11 }(xhr.responseText);
完整源码
001 Ajax =
002 function(){
003 function request(url,opt){
004 function fn(){}
005 opt = opt || {};
006 var async = opt.async !== false,
007 method = opt.method || 'GET',
008 type = opt.type || 'text',
009 encode = opt.encode || 'UTF-8',
010 timeout = opt.timeout || 0,
011 data = opt.data || null,
012 success = opt.success || fn,
013 failure = opt.failure || fn;
014 method = method.toUpperCase();
015 if(data && typeof data == 'object'){//对象转换成字符串键值对
016 data = _serialize(data);
017 }
018 if(method == 'GET' && data){
019 url += (url.indexOf('?') == -1 ? '?' : '&') + data;
020 data = null;
021 }
022 var xhr = function(){
023 try{
024 return new XMLHttpRequest();
025 }catch(e){
026 try{
027 return new ActiveXObject('Msxml2.XMLHTTP');
028 }catch(e){
029 try{
030 return new ActiveXObject('Microsoft.XMLHTTP');
031 }catch(e){
032 failure(null,'create xhr failed',e);
033 }
034 }
035 }
036 }();
037 if(!xhr){return;}
038 var isTimeout = false, timer;
039 if(async && timeout>0){
040 timer = setTimeout(function(){
041 xhr.abort();
042 isTimeout = true;
043 },timeout);
044 }
045 xhr.onreadystatechange = function(){
046 if (xhr.readyState == 4 && !isTimeout){
047 _onStateChange(xhr, type, success, failure);
048 clearTimeout(timer);
049 }else{}
050 };
051 xhr.open(method,url,async);
052 if(method == 'POST'){
053 xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded;charset=' + encode);
054 }
055 xhr.send(data);
056 return xhr;
057 }
058 function _serialize(obj){
059 var a = [];
060 for(var k in obj){
061 var val = obj[k];
062 if(val.constructor == Array){
063 for(var i=0,len=val.length;i<len;i++){
064 a.push(k + '=' + encodeURIComponent(val[i]));
065 }
066 }else{
067 a.push(k + '=' + encodeURIComponent(val));
068 }
069 }
070 return a.join('&');
071 }
072 function _onStateChange(xhr,type,success,failure){
073 var s = xhr.status, result;
074 if(s>= 200 && s < 300){
075 switch(type){
076 case 'text':
077 result = xhr.responseText;
078 break;
079 case 'json':
080
081 result = function(str){
082 try{
083 return JSON.parse(str);
084 }catch(e){
085 try{
086 return (new Function('return ' + str))();
087 }catch(e){
088 failure(xhr,'parse json error',e);
089 }
090 }
091 }(xhr.responseText);
092 break;
093 case 'xml':
094 result = xhr.responseXML;
095 break;
096 }
097 // text, 返回空字符时执行success
098 // json, 返回空对象{}时执行suceess,但解析json失败,函数没有返回值时默认返回undefined
099 typeof result !== 'undefined' && success(result);
100
101 //请求超时,调用abort后xhr.status为0,但不知为0时是否还有其它的情况
102 }else if(s===0){
103 failure(xhr,'request timeout');
104 }else{
105 failure(xhr,xhr.status);
106 }
107 xhr = null;
108 }
109 return (function(){
110 var Ajax = {request:request}, types = ['text','json','xml'];
111 for(var i=0,len=types.length;i<len;i++){
112 Ajax[types[i]] = function(i){
113 return function(url,opt){
114 opt = opt || {};
115 opt.type = types[i];
116 return request(url,opt);
117 }
118 }(i);
119 }
120 return Ajax;
121 })();
122 }();