最近做项目,遇到了Ajax同步异步和跨域的问题,整理总结如下:
关于同步、异步
手册中时这样写的,默认是异步,为了并行加载,尽量不要设置为同步,因为同步时浏览器会被锁死。
但根据实际情况而定,如果你需要通过请求Ajax来执行某些操作的时候,必须等这些操作执行完成之后,在继续执行,那么你需要设置为同步,即将async设置为false。但是需要注意的是,如果你请求的是JS文件或者是利用Ajax中的dataType属性为’jsonp’时,没有同步和异步的区别。下面具体说一下
首先说一下,同步、异步
先上代码:
$(document).ready(function(){
alert(0);
var a;
$.ajax({
type: 'get',
url : 'ajax.php',
async : false,
success:function(data){
a =
data;
alert(a);
}
});
alert(2);
});
这是一个简单的ajax请求,在ajax.php中直接echo 1;
在这里我们使用的是同步,(async:false),它的执行顺序是 alert 0 — 1 — 2
如果我们使用异步,即默认的方式,则其顺序为:alert 0 — 2 — 1
由此我们可以看出异步的意思是并行,即去请求的时候继续执行下面的代码,请求成功之后执行器success中的代码,这里有个complete选项,它和success只是返回的数据不一样,complete返回的是一个对象,不会影响其执行顺序。
其次说一下 加载JS文件和jsonp跨域请求
如果加载JS文件,返回的是JS脚本,如果加载JS之后,立刻调用其中的方法,可以使用JS加载器,代码如下:
function loadScript(url, callback){
var script =
document.createElement_x("script")
//script.type =
"text/javascript";
script.src =
url;
document.body.appendChild(script);
if (script.readyState){
//IE
script.onreadystatechange =
function(){
if
(script.readyState == "loaded" || script.readyState ==
"complete"){
script.onreadystatechange =
null;
callback();
}
};
} else { //Others:
Firefox, Safari, Chrome, and Opera
script.onload =
function(){
callback();
};
}
}
来看个例子
loadScript('http://www.xxx.com/md5.js',function(){
token = CryptoJS.MD5('abcdefghijklmn');
alert(token);
});
加载md5.js时,md5.js中有这样的一个方法—CryptoJS.MD5(),如果我们不在loadScript的回调函数中使用该方法,而在$(document).ready()中使用,或者在loadScript函数之外直接使用的话,会因为延时无法使用,提示改方法没有定义。
解决的方法
1. 在使用的页面直接加载,不用js加载JS文件(最保险)
2. 在加载JS文件之后,做延迟处理,如果不影响的话
3. 使用js加载器,回调函数中使用即可。(推荐)
Jquery中Ajax的跨域请求问题
如果使用jQuery中的ajax实现跨域,会使用到这个选项 dataType : ‘jsonp’;
具体如下:
在需要提交请求的页面(使用ajax的页面)
function success_jsonpCallback(data){
alert(data.info);
}
$.ajax({
type : "get",
async:false,
url : "http://www.xxx.com.cn/index.php",
dataType : "jsonp",
jsonp: "data",//服务端用于接收callback调用的function名的参数
jsonpCallback:"success_jsonpCallback",//callback的function名称
success : function(json){
alert(json);
},
error:function(){
alert('fail');
}
});
其中jsonp选项中的值为回调函数中的参数名,比如success_jsonpCallback为回调函数,其参数为data,jsonpCallback选项是设置回调函数的名字。
在PHP页面,也就是服务器端的代码是这样子的:
exit('success_jsonpCallback('.json_encode(array('info'=>'error')).')');
首先要使用返回回调函数的名字,然后函数的参数就是返回的数据。这里可能会遇到json_encode无法解析中文的问题,一会儿我们在第三个问题中详细来说。
这里还需要注意的是:
执行顺序问题。请求之后首先调用的是回调函数
success_jsonpCallbac,即先弹出error,然后再调用success处的函数,如果在ajax外部下面有其他代码,比如还有个alert(1);那么这个alert(1)会首先执行,即alert(1)—alert(data.info)—alert(json)
补充说明:(转自德问)
如果你有这样的需求,如果使用跨域,而且还需要同步执行,也就说跨域请求数据之后,要等数据返回之后,经过回调函数或者success后面的函数之后,可以尝试这样解决:
(1) 把你的处理逻辑写入ajax的success()回调函数中;
(2) 外部设置标志位, ajax的sucess()设置标志位. 外部代码setInterval轮询标志位.