ajax 请求long数据溢出的转换问题以及fetch api兼容性问题

旧的ajax请求对象:XmlHttpRequest

     XmlHttpRequest在web开发中,已经有很长时间,在使用上面只要网页里牵涉到异步加载的,几乎都是使用XmlHttpRequest这个对象进行异步数据访问。由于时间长,所以各大浏览器/手机/pc等都对其api支持比较完善。以下是在项目中些的一个公共的ajax,这里备注以下

//这是最终执行ajax的方法,里面做了很多判断 

var XmlHttpPost = function(data) {
  try {
   _appurl = data.serverInterface != undefined ? _interfaceAppUrl.format(data.serverInterface) : _appurl;
  } catch(e) {
   //TODO handle the exception
  }
  var ajaxData = {
   type: "post",
   contentType: data.contentType ? data.contentType : "application/json;charset=utf-8",
   async: data.sync ? data.sync : false,
   timeout: data.timeout ? data.timeout : 5000,
   url: data.url ? data.url : _appurl,
   dataType: data.dataType ? data.dataType : 'json',
   data: data.data ? data.data : "",
   jsonp: data.jsonp ? data.jsonp : "weicyjsoncallback",
   success: data.success ? data.success : function(result) {
    if(_AppDebug) {
     console.log(result)
    }
   },
   complete: data.complete ? data.complete : completeDefault,
   error: data.error ? data.error : function(er) {
    try {
     mui.toast("访问出错,请检查网络连接");
    } catch(e) {
     //TODO handle the exception
     alert("访问出错");
    }
   }
  };
  excFunctionAjax(ajaxData);
 }

    var excFunctionAjax = function(ajaxData) {
   var next = GetUrlRelativePath(); //获取房钱的url
   var first = GetUrlRelativePath(ajaxData.url);//获取ajaxData对象传入的url
   //如果不是jsonp,并且域名不相同,或者链接里面域名为null,则进行普通的ajax请求
   if((ajaxData.dataType != 'jsonp') || (first.domain == next.domain) || first.domain == "") {
    //判断地址是否有效,若无效
    if(ajaxData.dataType == 'jsonp') {
     ajaxData.dataType = "json";
    }
    if(!tools.Kit.isURL(ajaxData.url)) {
     //地址无效,判断配置是否是tomcat根目录,若是,则进行if,否则进行else
     if(Kit_Config.isRoot) {
      ajaxData.url = next.httpType + next.domain + ajaxData.url;
     } else {
      ajaxData.url = next.httpType + next.domain + Kit_Config.webProject + ajaxData.url;
     }
    } else { //若是有效域名,则对域名进行相应的封装请求
     //ajaxData.url = next.httpType+next.domain+first.url;
    }
    //进行ajax请求
    if(_AppDebug) {
     console.log(ajaxData.type + "请求的url:" + ajaxData.url);
    }
    //alert("ajax+++"+JSON.stringify(ajaxData));
    $.ajax({
     type: ajaxData.type,
     url: ajaxData.url,
     data: ajaxData.data,
     contentType: ajaxData.contentType || "application/x-www-form-urlencoded; charset=UTF-8",
     headers: {
      "openid": localToken[0],
      "token": localToken[1],
      'url': window.location.href
     },
     dataType: "text",
     success: function(data) {
      if(ajaxData.type == "GET" || ajaxData.type == 'get'){
       data = data.replace(/:\s\d{18}/g, ":\"@!#@!#$&\"").replace(/:\d{18}/g, ":\"@!#@!#$&\"").replace(/@!#@!#:\s/g,"").replace(/@!#@!#:/g,"");
       
      }
      data = JSON.parse(data);
      ajaxData.success(data);
     },
     complete: function(XMLHttpRequest, status) {
      ajaxData.complete(XMLHttpRequest, status);
     },
     error: function(er) {
      console.log(er);
      ajaxData.error(er);
     }
    });
   } else {
    //不用验证,直接进行ajax请求
    $.ajax({
     type: ajaxData.type,
     url: ajaxData.url,
     dataType: "text",  //上面ajaxData中已经传入了相应的dataType格式,但是这里直接写死是因为项目中有一个需求,会返回一个很长的Long类型的数据,如果按照json传递过来,在ajax内部会使用JSON.parse()进行转换,这样由于服务器的long和javascript的long位数不同,所以会造成溢出。所以最终得到的long并非服务器的long,而是截取之后的long。网上有一个bigint的js库,但是只适用于单个数据,服务器传递过来又不可能是单个数据,所以这里直接以文本方式进行接送,然后本地通过正则表达式进行处理。
     data: ajaxData.data,
     headers: {
      "openid": localToken[0],
      "token": localToken[1],
      'url': window.location.href
     },
     contentType: ajaxData.contentType || "application/x-www-form-urlencoded; charset=UTF-8",
     success: function(data) {
      if(ajaxData.type == "GET" || ajaxData.type == 'get'){//只转换get请求的,因为post请求的一般不会返回很长的数据。如果项目有需求可以释放这里为全部,这里只是将等于18位的给转换了
       data = data.replace(/:\s\d{18}/g, ":\"@!#@!#$&\"").replace(/:\d{18}/g, ":\"@!#@!#$&\"").replace(/@!#@!#:\s/g,"").replace(/@!#@!#:/g,"");
      }
      data = JSON.parse(data);//因为得到的是text文本,所以这里要将文本转换为json对象传递给外部使用
      ajaxData.success(data);
     },
     complete: function(XMLHttpRequest, status) {
      ajaxData.complete(XMLHttpRequest, status);
     },
     error: function(er) {
      console.log(er);
      ajaxData.error(er);
     }
    });
   }
  }

  var GetUrlRelativePath = function(relUrl) {
  var url = relUrl || window.location.href.toString();
  if(!tools.Kit.isURL(url)) {
   var urlPath = {
    httpType: "", //返回http方式
    domain: "", //返回域名
    url: url //返回url地址
   };
   return urlPath;
  } else {
   var arrUrl = url.split("//");
   var start = arrUrl[1].indexOf("/");
   var domain = arrUrl[1].substring(0, start);
   var relUrl = arrUrl[1].substring(start); //stop省略,截取从start开始到结尾的所有字符
   //   if(relUrl.indexOf("?") != -1){
   //   relUrl = relUrl.split("?")[0];
   //   }
   var urlPath = {
    httpType: arrUrl[0] + "//", //返回http方式
    domain: domain, //返回域名
    url: relUrl //返回url地址
   };
   return urlPath;
  }
 }

上面就是xmlhttprequest的自己的封装,当时包含了跨域自动判断,但是由于项目不需要(使用服务器的corse),所以删除了。【注意,ajax jsonp只支持get,因为它是通过将服务器数据封装了一个javascript代码,引用javascript是不用考虑跨域的这样解决的】

 

新的ajax请求对象:fetch

因为新的fetch 在浏览器的支持还不是太完善【pc基本完全支持,手机端主要表现在iphone6s 以下的机型】,主要表现为,机型支持fetch,但是支持的不完全,就会导致有一些地方会出现莫名其妙的错误。大部分浏览器能够访问到后台,但是后台传递过来的数据在前端解析就会出现类型错误TypeError等问题

var fetchPost = function(data) {

  try {
   _appurl = data.serverInterface != undefined ? _interfaceAppUrl.format(data.serverInterface) : _appurl;

  } catch(e) {
   //TODO handle the exception
  }
  var _postData = new FormData();
  _postData.append("json", data.data || "");

  /*
  try {
    let response = await fetch(data.url || _appurl,{method: "POST",body:_postData});
     let _dataAwait = await response.json();
     console.log(_dataAwait);
     return _dataAwait;
    
  } catch(e) {
    console.log("Oops, error", e);
  }
  */
  fetch(data.url || _appurl, {
   method: "POST",
   headers: {
    'Accept': 'application/json, text/javascript, */*; q=0.01',
    'Content-Type': 'application/json;charset=UTF-8',
    'openid': localToken[0],
    'token': localToken[1],
    'url': window.location.href
   },
   body: data.data
  }).then(function(rsp) {
   if(rsp.ok) {
    //console.log(response);
    //data.success(rsp.json());
    //console(BigInteger(res.json())+"+++");
    
    return rsp.json();
   } else {
    console.log("error fetch");
   }
  }).then(function(dataJSON) {
   data.success(dataJSON);
   if(_AppDebug) {
    console.log("POST地址:" + data.url || _appurl);
    console.log("debug======:" + JSON.stringify(dataJSON));
   }
  }).catch(function(e) {
   if(_AppDebug) {
    console.log("POST地址:" + data.url || _appurl);
    console.log("debug====:error ajax " + e);
   }
   try {
    //alert("错误日志:"+e);
    mui.toast("访问出错,请检查网络连接");
   } catch(e) {
    //TODO handle the exception
    alert("访问出错");
   }
  })

 


版权声明:本文为wangganggelian原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。