java处理ajax异步请求_JavaScrpit中异步请求Ajax实现
在前端页⾯开发的过程中,经常使⽤到Ajax请求,异步提交表单数据,或者异步刷新页⾯。
⼀般来说,使⽤Jquery中的$.ajax,$.post,$.getJSON,⾮常⽅便,但是有的时候,我们只因为需要ajax功能⽽引⼊Jquery⽐较不划算。
所以接下来便⽤原⽣JavaScrpit实现⼀个简单的Ajax请求,并说明ajax请求中的跨域访问问题,以及多个ajax请求的数据同步问题。
JavaScript实现Ajax异步请求
简单的ajax请求实现
Ajax请求的原理是创建⼀个XMLHttpRequest对象,使⽤这个对象来进⾏异步发送请求,具体实现参考下⾯代码:
functionajax(option) {//创建⼀个 XMLHttpRequest 对象
var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"),
requestData=option.data,
requestUrl=option.url,
hod;//如果是GET请求,需要将option中的参数拼接到URL后⾯
if ('POST' != requestMethod &&requestData) {var query_string = '';//遍历option.data对象,构建GET查询参数
for(var item inrequestData) {
query_string+= item + '=' + requestData[item] + '&';
}//注意这⼉拼接的时候,需要判断是否已经有 ?
requestUrl.indexOf('?') > -1
requestUrl = requestUrl + '&' +query_string
: requestUrl= requestUrl + '?' +query_string;//GET 请求参数放在URL中,将requestData置为空
requestData = null;
}//ajax 请求成功之后的回调函数
if (adyState == ("number" == typeof XMLHttpRequest.DONE ? XMLHttpRequest.DONE : 4)) {if (200 == xhr.status) { //判断状态码
var response = sponse || sponseText || {}; //获取返回值
//if define success callback, call it, if response is string, convert it to json objcet
console.log(response);
option.success && option.success(response); // 调⽤成功的回调函数处理返回值//可以判断返回数据类型,对数据进⾏JSON解析或者XML解析
//option.success && option.success('string' == typeof response ? JSON.parse(response) : response);
} else{//if define error callback, call it
< &&(xhr, xhr.statusText);
}
}
};//发送ajax请求
xhr.open(requestMethod, requestUrl, true);//请求超时的回调
option.timeout&&option.timeout(xhr, xhr.statusText);
};//定义超时时间
xhr.timeout = option.timeout || 0;//设置响应头部,这⼉默认设置为json格式,可以定义为其他格式,修改头部即可
xhr.setRequestHeader && xhr.setRequestHeader('Content-Type', 'application/json;charset=utf-8');
xhr.withCredentials= (option.xhrFields ||{}).withCredentials;//这⼉主要⽤于发送POST请求的数据
xhr.send(requestData);
}
上⾯的代码中有详细的注释,ajax的原理很简单,总的来说就是使⽤XMLHttpRequest对象来发送数据。这⼉对这个对象进⾏补充说明。jquery ajax例子
代码中⽤了很多布尔表达式的短路特性代替条件语句的写法,善⽤布尔表达式的短路特性能让⼤量简单的条件语句简化。^_^
XMLHttpRequest对象的基本属性
readyState属性有五个状态值:
0:是uninitialized:未初始化。已经创建了XMLHttpRequest对象但是未初始化。
1:是loading:已经开始准备好要发送了。
2:是loaded,:已经发送,但是还没有收到响应。
3:是interactive:正在接受响应,但是还没接收完。
4:是completed:接受响应完毕。
responseText:服务器返回的响应⽂本。只有当readyState>=3的时候才有值。当readyState=3,返回的响应⽂本不完整,只有readyState=4,接收到完整的响应⽂本。 responseXML:响应信息是xml,可以解析为Dom对象。 status:服务器的Http状态码,若是200,则表⽰OK,404,表⽰为未到。 statusText:服务器http状态码的⽂本。⽐如OK,Not Found。
XMLHttpRequest对象的基本⽅法
open(method,url,asyn):打开XMLHttpRequest对象。其中method⽅法有get,post,delete,put。url是请求资源的地址。第三个参数表⽰是否使⽤异步。默认情况是true,因为Ajax的特点就是异步传送。若使⽤同步则false。 send(body):发送请求Ajax。其中发送的内容可以是需要的参数,若是没有参数,直接send(null)
使⽤⽅法
直接调⽤上⾯定义的ajax函数,传送相应的选项和参数即可。
ajax({
url:'/post.php',
data: {
name:'uusama',
desc:'smart'},
method:'GET',
success:function(ret) {
console.log(ret);
}
});
跨域请求问题
使⽤ajax请求的时候,⼀定要注意⼀个问题:跨域请求。 在没有使⽤特殊⼿段的情况下,跨域请求:请求其他域名和端⼝下的URL资源的时候,会报 Access-Control-Allow-Origin 相关的错误。其主要原因是浏览器的同源策略限制,浏览器规定不能跨域请求资源。
解决办法
下⾯简单的提⼀下⼀些解决⽅案。 在ajax头部添加允许跨域请求的header,这种⽅式还需要服务端配合添加允许跨域请求的头部才可以。下⾯是PHP添加允许POST请求跨域头部的PHP⽰例:
//指定允许其他域名访问
header('Access-Control-Allow-Origin:*');//响应类型
header('Access-Control-Allow-Methods:POST');//响应头设置
header('Access-Control-Allow-Headers:x-requested-with,content-type');
使⽤动态scrpit标签,动态创建⼀个scrpit标签并指向请求的地址的⽅法,也就是JSONP⽅式,需要在URL后⾯拼接⼀个回调函数,标签加载成功以后会调⽤回调函数。
var url = "uusama", callbaclName = 'jsonpCallback';
script = ateElement('script');
script.src = url + (url.indexOf('?') > -1 ? '&' : '?') + 'callback=' + callbaclName;
document.body.appendChild(script);
回调函数需要设置为全局函数:
window['jsonpCallback'] = function jsonpCallback(ret) {}
多个ajax请求数据同步问题
单个ajax返回数据异步处理
多个ajax请求互不相关,它们在被调⽤以后发送各⾃请求,请求成功以后调⽤⾃⼰的回调⽅法,互不影响。 因为ajax请求异步的特性,所有⼀些依赖于请求完成之后的操作我们都需要放在回调函数内部,否则的话,你在回调函数外⾯读取到的值是空。看下⾯的例⼦:
var result = null;
ajax({
url:'/get.php?id=1',
method:'GET',
success:function(ret) {
result=ret;
}
});
console.log(result);//输出 null
虽然我们在回调函数⾥⾯设置了result的值,但是在最后⼀⾏ console.log(result); 输出为空。 因为ajax请求是异步的,程序执⾏到最后⼀⾏的时候,请求并没有完成,值并没有来得及修改。 这⼉我们应该把 console.log(result) 相关的处理,放在 success 回调函数中才可以。
多个ajax返回数据问题
如果有多个ajax请求,情况会变得有些复杂。 如果多个ajax请求是按照顺序执⾏的,其中⼀个完成之后,才能进⾏下⼀个,则可以把后⾯⼀个请求放在前⼀后请求的回调中。 ⽐如有两个ajax请求,其中⼀个请求的数据依赖于另外⼀个,则可以在第⼀个请求的回调⾥⾯再进⾏ajax 请求:
//⾸先请求第⼀个ajax
ajax({
url:'/get1.php?id=1',
success:function(ret1) {//第⼀个请求成功回调以后,再请求第⼆个
if(ret1) {
ajax({
url:'/get2.php?id=4',
success:function(ret2) {
console.log(ret1);
console.log(ret2)
}
})
}
}
});//也可以写成下⾯的形式
var ajax2 = function(ret1) {
ajax({
url:'/get2.php?id=4',
success:function(ret2) {
console.log(ret1);
console.log(ret2)
}
});
};
ajax({
url:'/get1.php?id=1',
success:function(ret1) {if(ret1){
ajax2(ret1);
}
}
});
如果不关⼼不同的ajax请求的顺序,⽽只是关⼼所有请求都完成,才能进⾏下⼀步。 ⼀种⽅法是可以在每个请求完成以后都调⽤同⼀个回调函数,只有次数减少到0才执⾏下⼀步。
var count = 3, all_ret = []; //调⽤3次
ajax({
url:'/get1.php?id=1',
success:function(ret) {
callback(ret);
}
});
ajax({
url:'/get2.php?id=1',
success:function(ret) {
callback(ret);
}
});
ajax({
url:'/get3.php?id=1',
success:function(ret) {
callback(ret);
}
});functioncallback(ret) {if (count > 0) {
count--;//可以在这⼉保存 ret 到全局变量
all_ret.push(ret);return;
}else { //调⽤三次以后
//todo
console.log(ret);
}
}
另⼀种⽅法是设置⼀个定时任务去轮训是否所有ajax请求都完成,需要在每个ajax的成功回调中去设置⼀个标志。 这⼉可以⽤是否获得值来判断,也可以设置标签来判断,⽤值来判断时,要注意设置的值和初始相同的情况。
var all_ret ={
ret1:null, // 第⼀个ajax请求标识
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论