在jquery中ajax请求一半情况下使用异步执行,单有时也会又特殊需求使用同步,此时如果想要诸如显示loading等待框,执行请求,关闭loading等待框时就会出现问题。首先loading等待框居然不出现,
原因是这样的:
原因就是ajax的async设置为true时,ajax会委托浏览器另起一个线程,此线程与js线程和ui线程不冲突,只是在执行完成后再插入js事件环。而ajax的async设置为false时并没有启动单独的线程,还是在js主线程中执行,所以会与浏览器的渲染(UI)线程和js线程是互斥的,在执行js耗时操作时,页面渲染会被阻塞掉。当我们执行异步ajax的时候没有问题,但当设置为同步请求时,其他的动作(ajax函数后面的代码,还有渲染线程)都会停止下来。即使我的DOM操作语句是在发起请求的前一句,这个同步请求也会“迅速”将UI线程阻塞,不给它执行的时间。这就是代码失效的原因。
这时使用settimeout也是不可行的,因为setTimeout并不是异步的,而是将其操作插入到js线程中,排队执行,造成异步的假象。
正确的解决方法是使用#######deferred
举个简单的小例子
使用前:
function toGetData() {
var defer = $.Deferred();
$.ajax({
url: ' https://api.itooi.cn/music/tencent/search?key=579621905&s=123&limit=10&offset=0&type=song',
type: "get", // 请求类型
dataType: 'json',
async: true, // 是否异步
success: function (ret) {
console.log('2');
}
});
return defer;
}
$('button').click(function(){
$(".shadow").show()
console.log('1');
toGetData();
console.log('3');
})
依次输出1,3,2
使用后:
function toGetData() {
var defer = $.Deferred();
$.ajax({
url: ' https://api.itooi.cn/music/tencent/search?key=579621905&s=123&limit=10&offset=0&type=song',
type: "get", // 请求类型
dataType: 'json',
async: true, // 是否异步
success: function (ret) {
console.log('2');
defer.resolve(ret)
}
});
return defer;
}
$('button').click(function(){
$(".shadow").show()
console.log('1');
$.when(toGetData()).done(function(ret){
$(".shodow").hide();
console.log('3');
});
})
依次输出1,2,3