原生JS发送异步数据请求
在做项目的时候,有时候需要用到异步数据请求,但是如果这个时候没有框架的依赖,就需要用到原生JS进行异步数据请求。这时候无非有两种请求方式,一种是AJAX,另一个是JSONP。通过原生JS对异步请求进行简单的封装。
AJAX
AJAX是一种数据请求方式,不需要刷新整个页面就能够更新局部页面的数据。AJAX的技术核心是XMLHttpRequest对象,主要请求过程如下:
- 创建XMLHttpRequest对象(new)
- 连接服务器(open)
- 发送请求(send)
- 接收响应数据(onreadystatechange)
不说话直接贴代码
/**
*通过JSON的方式请求
*@param{[type]}params[description]
*@return{[type]}[description]
*/
ajaxJSON(params){
params.type=(params.type||'GET').toUpperCase();
params.data=params.data||{};
varformatedParams=this.formateParams(params.data,params.cache);
varxhr;
//创建XMLHttpRequest对象
if(window.XMLHttpRequest){
//非IE6
xhr=newXMLHttpRequest();
}else{
xhr=newActiveXObject('Microsoft.XMLHTTP');
}
//异步状态发生改变,接收响应数据
xhr.onreadystatechange=function(){
if(xhr.readyState==4&&xhr.status==200){
if(!!params.success){
if(typeofxhr.responseText=='string'){
params.success(JSON.parse(xhr.responseText));
}else{
params.success(xhr.responseText);
}
}
}else{
params.error&¶ms.error(status);
}
}
if(params.type=='GET'){
//连接服务器
xhr.open('GET',(!!formatedParams?params.url+'?'+formatedParams:params.url),true);
//发送请求
xhr.send();
}else{
//连接服务器
xhr.open('POST',params.url,true);
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
//发送请求
xhr.send(formatedParams);
}
},
/**
*格式化数据
*@param{Obj}data需要格式化的数据
*@param{Boolean}isCache是否加入随机参数
*@return{String}返回的字符串
*/
formateParams:function(data,isCache){
vararr=[];
for(varnameindata){
arr.push(encodeURIComponent(name)+'='+encodeURIComponent(data[name]));
}
if(isCache){
arr.push('v='+(newDate()).getTime());
}
returnarr.join('&');
}
IE7及其以上版本中支持原生的XHR对象,因此可以直接用:varoAjax=newXMLHttpRequest();。IE6及其之前的版本中,XHR对象是通过MSXML库中的一个ActiveXObject对象实现的。
通过xhr的open函数来连接服务器,主要接收三个参数:请求方式、请求地址和是否异步请求(一般都是异步请求)。请求方式有两种,GET和POST,GET是通过URL将数据提交到服务器的,POST则是通过将数据作为send方法的参数发送到服务器。
给xhr绑定状态改变函数onreadystatechange,主要用来检测xhr的readyState的变化,当异步发送成功后,readyState的数值会由0变成4,同时触发onreadystatechange事件。readyState的属性及对应状态如下:
0(未初始化)对象已建立,但是尚未初始化(尚未调用open方法)
1(初始化)对象已建立,尚未调用send方法
2(发送数据)send方法已调用,但是当前的状态及http头未知
3(数据传送中)已接收部分数据,因为响应及http头不全,这时通过responseBody和responseText获取部分数据会出现错误
4(完成)数据接收完毕,此时可以通过通过responseBody和responseText获取完整的回应数据
在readystatechange事件中,先判断响应是否接收完成,然后判断服务器是否成功处理请求,xhr.status是状态码,状态码以2开头的都是成功,304表示从缓存中获取,上面的代码在每次请求的时候都加入了随机数,所以不会从缓存中取值,故该状态不需判断。
JSONP
如果还是用上面的XMLHttpRequest对象来发送需要跨域的请求,虽然调用了send函数,但是xhr的状态一直都是0,也不会触发onreadystatechange事件,这个时候就要用到JSONP的请求方式了。
JSONP(JSONwithPadding)是一种跨域请求方式。主要原理是利用了script标签可以跨域请求的特点,由其src属性发送请求到服务器,服务器返回js代码,网页端接受响应,然后就直接执行了,这和通过script标签引用外部文件的原理是一样的。
JSONP由两部分组成:回调函数和数据,回调函数一般是由网页端控制,作为参数发往服务器端,服务器端把该函数和数据拼成字符串返回。
比如网页端创建一个script标签,并给其src赋值为http://www.test.com/json/?callback=process,此时网页端就发起一个请求。服务端将要返回的数据拼作为函数的参数传入,服务端返回的数据格式类似”process({‘name:'xieyufei'})”,网页端接收到了响应值,因为请求者是script,所以相当于直接调用process方法,并且传入了一个参数。
不说话直接贴代码。
/**
*通过JSONP的方式请求
*@param{[type]}params[description]
*@return{[type]}[description]
*/
ajaxJSONP(params){
params.data=params.data||{};
params.jsonp=params.jsonp||'callback';
//设置传递给后台的回调参数名和参数值
varcallbackName='jsonp_'+(newDate()).getTime();
params.data[params.jsonp]=callbackName;
varformatedParams=this.formateParams(params.data,params.cache);
//创建script标签并插入到页面中
varhead=document.getElementsByTagName('head')[0];
varscript=document.createElement('script');
head.appendChild(script);
//创建jsonp回调函数
window[callbackName]=function(json){
head.removeChild(script);
clearTimeout(script.timer);
window[callbackName]=null;
params.success&¶ms.success(json);
};
//发送请求
script.src=(!!formatedParams?params.url+'?'+formatedParams:params.url);
//为了得知此次请求是否成功,设置超时处理
if(params.time){
script.timer=setTimeout(function(){
window[callbackName]=null;
head.removeChild(script);
params.error&¶ms.error({
message:'超时'
});
},params.time);
}
}
给script标签设置src属性时浏览器就会去发送请求,但是只能发送一次请求,导致script标签不能复用,因此每次操作完都需要把script标签移除。在浏览器发送请求之前给全局绑定一个回调函数,当数据请求成功时就会调用这个回调函数。
总结
将两种发送异步数据的方式整合起来,根据dataType来进行判断选用哪种方式。贴上完整的代码
varxyfAjax={
ajax:function(params){
params=params||{};
params.cache=params.cache||false;
if(!params.url){
thrownewError('参数不合法');
}
params.dataType=(params.dataType||'json').toLowerCase();
if(params.dataType=='jsonp'){
this.ajaxJSONP(params);
}elseif(params.dataType=='json'){
this.ajaxJSON(params);
}
},
/**
*通过JSONP的方式请求
*@param{[type]}params[description]
*@return{[type]}[description]
*/
ajaxJSONP(params){
params.data=params.data||{};
params.jsonp=params.jsonp||'callback';
//设置传递给后台的回调参数名和参数值
varcallbackName='jsonp_'+(newDate()).getTime();
params.data[params.jsonp]=callbackName;
varformatedParams=this.formateParams(params.data,params.cache);
//创建script标签并插入到页面中
varhead=document.getElementsByTagName('head')[0];
varscript=document.createElement('script');
head.appendChild(script);
//创建jsonp回调函数
window[callbackName]=function(json){
head.removeChild(script);
clearTimeout(script.timer);
window[callbackName]=null;
params.success&¶ms.success(json);
};
//发送请求
script.src=(!!formatedParams?params.url+'?'+formatedParams:params.url);
//为了得知此次请求是否成功,设置超时处理
if(params.time){
script.timer=setTimeout(function(){
window[callbackName]=null;
head.removeChild(script);
params.error&¶ms.error({
message:'超时'
});
},params.time);
}
},
/**
*通过JSON的方式请求
*@param{[type]}params[description]
*@return{[type]}[description]
*/
ajaxJSON(params){
params.type=(params.type||'GET').toUpperCase();
params.data=params.data||{};
varformatedParams=this.formateParams(params.data,params.cache);
varxhr;
//创建XMLHttpRequest对象
if(window.XMLHttpRequest){
//非IE6
xhr=newXMLHttpRequest();
}else{
xhr=newActiveXObject('Microsoft.XMLHTTP');
}
//异步状态发生改变,接收响应数据
xhr.onreadystatechange=function(){
if(xhr.readyState==4&&xhr.status==200){
if(!!params.success){
if(typeofxhr.responseText=='string'){
params.success(JSON.parse(xhr.responseText));
}else{
params.success(xhr.responseText);
}
}
}else{
params.error&¶ms.error(status);
}
}
if(params.type=='GET'){
//连接服务器
xhr.open('GET',(!!formatedParams?params.url+'?'+formatedParams:params.url),true);
//发送请求
xhr.send(null);
}else{
//连接服务器
xhr.open('POST',params.url,true);
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
//发送请求
xhr.send(formatedParams);
}
},
/**
*格式化数据
*@param{Obj}data需要格式化的数据
*@param{Boolean}isCache是否加入随机参数
*@return{String}返回的字符串
*/
formateParams:function(data,isCache){
vararr=[];
for(varnameindata){
arr.push(encodeURIComponent(name)+'='+encodeURIComponent(data[name]));
}
if(isCache){
arr.push('v='+(newDate()).getTime());
}
returnarr.join('&');
}
}
xyfAjax.ajax({
url:'http://www.xieyufei.com',
type:'get',//orpost
dataType:'json',//orjsonp
data:{
name:'xyf'
},
success:function(data){
console.log(data)
}
})
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。