今天做一个需求遇到了这么个情况,就是用户个人中心有个功能,点击按钮,可以刷新用户当前的积分,这个肯定需要使用到ajax的同步请求了,当时喀喀喀三下五除二写玩了,大概代码如下:

/**
* 异步当前用户积分 by zgw 20161216
* @return {[type]} [description]
*/
function flushIntegralSum() {
     //点击按钮刷新前修改按钮的文案,已经去掉点击事情,防止多次点击
$("#flushbutton").replaceWith('<a style="color:#3fb0ff;font-size:14px;" href="javascript:void(0);" id="flushbutton">正在刷新</a>');
$.ajax({
url:'URL',
type:'post',
async:false,
// data:{},
success:function(json){
json = eval('('+json+')');
if(json.url){window.location.href=json.url;return;}
$("#flushbutton").replaceWith('<a style="color:#3fb0ff;font-size:14px;" href="javascript:void(0);" onclick="flushFreeSum();" id="flushbutton">刷新积分</a>');
if(json.code!=1){
alert(json.msg);
}else{
$("#free_sum").html(json.free_sum);
}
return;
}
});
}

本以为这么简单的功能喀喀喀随便写写就没事了,在运行的时候出现了问题,当用户点击刷新积分按钮时,文案没有修改为"正在刷新",但是ajax请求发送了,于是我查看网页代码,发现js其实把文案和html元素绑定的onclick事件去掉了,在请求成功后有变回原来的了,但是页面上边文案没有改变,当时很奇怪,不知道为什么html代码里边改变了,页面却没有变点变化

二、了解问题原因

  问题的根源:当时我进行了排查,最后发现是 "async:false" 的问题,换成异步的就没有问题了,那为什么同步请求会产生代码失效的问题呢?

  原因:浏览器的渲染(UI)线程和js线程是互斥的,在执行js耗时操作时,页面渲染会被阻塞掉。当我们执行异步ajax的时候没有问题,但当设置为同步请求时,其他的动作(ajax函数后面的代码,还有渲染线程)都会停止下来。即使我的DOM操作语句是在发起请求的前一句,这个同步请求也会“迅速”将UI线程阻塞,不给它执行的时间。这就是代码失效的原因。

三、解决问题

  1.我当时使用了 setTimeout 来解决,把ajax代码放在sestTimeout中,让浏览器重启一个线程来操作,这样就解决问题了,代码如下:

function flushIntegralSum() {
     //点击按钮刷新前修改按钮的文案,已经去掉点击事情,防止多次点击
$("#flushbutton").replaceWith('<a style="color:#3fb0ff;font-size:14px;" href="javascript:void(0);" id="flushbutton">正在刷新</a>');
setTimeout(function(){
$.ajax({
url:'URL',
type:'post',
async:false,
// data:{},
success:function(json){
json = eval('('+json+')');
if(json.url){window.location.href=json.url;return;}
$("#flushbutton").replaceWith('<a style="color:#3fb0ff;font-size:14px;" href="javascript:void(0);" onclick="flushFreeSum();" id="flushbutton">刷新积分</a>');
if(json.code!=1){
alert(json.msg);
}else{
$("#free_sum").html(json.free_sum);
}
return;
}
});
},0)
}

setTimeout的第二个参数设为0,浏览器会在一个已设的最小时间后执行

  到这里问题就解决了,但是你可以试试当你点击按钮的时候如果需要弹出一个gif图片,并且图片一直在旋转,提示更新中,你会发现图片虽然会显示,但是图片却是不动的,那是因为虽然同步请求延迟执行了,但是它执行期间还是会把UI线程给阻塞。这个阻塞相当牛逼,连gif图片都不动了,看起来像一张静态图片一样。结论很明显,setTimeout治标不治本,相当于把同步请求“稍稍”异步了一下,接下来还是会进入同步的噩梦,阻塞线程,这种方法只适合发请求之前操作简单的时间短的情况

2.使用 Deferred 来解决

jQuery在1.5版本之后,引入了Deferred对象,提供的很方便的广义异步机制。

function getData3(){        var defer = $.Deferred();
$.ajax({
url : 'p.php', //async : false,
success: function(data){
defer.resolve(data)
}
}); return defer.promise();
}
$('.btn3').click(function(){
$('.loadingicon').show();
$.when(getData3()).done(function(data){
$('.loadingicon').hide();
alert(data);
});
});

可以看到我在ajax请求中去掉了async:false,也就是说,这个请求又是异步的了。另外请注意success函数中的这一句:defer.resolve(data),Deferred对象的resolve方法可传入一个参数,任意类型。这个参数可以在done方法中拿到,所以我们异步请求来的数据就可以以这样的方式来返回了。

  至此,问题得到了解决。Deferred对象如此强大且方便,我们可以好好利用它。

<button class="btn1">async:false</button><button class="btn2">setTimeout</button><button class="btn3">deferred</button>
<img class="loadingicon" style="position:fixed;left:50%;top:50%;margin-left:-16px;margin-top:-16px;display:none;" src="loading2.gif" alt="正在加载" /><script>
function getData1(){ var result;
$.ajax({
url : 'p.php',
async : false,
success: function(data){
result = data;
}
}); return result;
}
$('.btn1').click(function(){
$('.loadingicon').show(); var data = getData1();
$('.loadingicon').hide();
alert(data);
}); $('.btn2').click(function(){
$('.loadingicon').show();
setTimeout(function(){
$.ajax({
url : 'p.php',
async : false,
success: function(data){
$('.loadingicon').hide();
alert(data);
}
});
}, 0);
}); function getData3(){ var defer = $.Deferred();
$.ajax({
url : 'p.php', //async : false, success: function(data){
defer.resolve(data)
}
}); return defer.promise();
}
$('.btn3').click(function(){
$('.loadingicon').show();
$.when(getData3()).done(function(data){
$('.loadingicon').hide();
alert(data);
});
});</script>

全部代码

jQuery Ajax async=>false异步改为同步时,导致浏览器假死的处理方法的更多相关文章

  1. jQuery Ajax同步参数导致浏览器假死怎么办

    俗话说不作死就不会死,今天作死了一回,写了一个比较二逼的函数,遇到了同步Ajax引起的UI线程阻塞问题,在此记录一下.   事情起因是这样的,因为页面上有多个相似的异步请求动作,本着提高代码可重用性的 ...

  2. async:false同步请求,浏览器假死

    // 异步请求导致数据错乱 // function get_num(){ // $("input[name='monitor']").eq(1).attr('checked',tr ...

  3. 如何将Ajax请求从异步改为同步

    Ajax请求默认的都是异步的 如果想同步 async设置为false就可以(默认是true) var html = $.ajax({   url: "some.PHP",   as ...

  4. js ajax同步请求造成浏览器假死的问题

    一.问题的起因 今天做一个需求遇到了这么个情况,就是用户个人中心有个功能,点击按钮,可以刷新用户当前的积分,这个肯定需要使用到ajax的同步请求了,当时喀喀喀三下五除二写玩了,大概代码如下: /** ...

  5. jquery ajax success 函数 异步调用方法中不能给全局变量赋值的原因及解决办法

    jquery ajax success 函数 异步调用方法中不能给全局变量赋值的原因及解决办法   在调用一个jquery的ajax方法时我们有时会需要该方法返回一个值或者给某个全局变量赋值,可是我们 ...

  6. jQuery ajax async

    jQuery 同步调用: jQuery.ajax({ type:'POST', async: false, url:'qcTask/add', contentType:'application/jso ...

  7. jQuery+Ajax+PHP实现异步分页数据显示

    这几天做毕业设计的时候需要使用到一个异步分页的功能,即翻页的时候只是刷新分页的数据而不是刷新整个页面.因为之前做项目的时候没有做过这方面的功能,所以还是纠结了挺长时间的,在网上也找了很多资料,结合自己 ...

  8. jquery ajax中支持哪些返回类型以及js中判断一个类型常用的方法?

    1 jquery ajax中支持哪些返回类型在JQuery中,AJAX有三种实现方式:$.ajax() , $.post , $.get(). 预期服务器返回的数据类型.如果不指定,jQuery 将自 ...

  9. jQuery+Ajax滚屏异步加载数据实现(附源码)

    一.CSS样式 body { font:12px/1.0em Microsoft Yahei; line-height:1.6em; background:#fff; line-height:1.2e ...

随机推荐

  1. ssl 原理简介

    要想弄明白SSL认证原理,首先要对CA有有所了解,它在SSL认证过程中有非常重要的作用.说白了,CA就是一个组织,专门为网络服务器颁发证书的,国际知名的CA机构有VeriSign.Symantec,国 ...

  2. rancher2基础环境配置

    一.主机配置 1.配置要求 参考节点要求 2.主机名配置 因为K8S的规定,主机名只支持包含 - 和 .(中横线和点)两种特殊符号,并且主机名不能出现重复. 3.Hosts 配置每台主机的hosts( ...

  3. jmeter(五十一)_性能测试中的服务器资源监控与分析

    概述 性能测试过程中,对服务器资源的监控是必不可少的.这里的资源又分了两块,windows和linux   linux下监控资源 访问网址http://jmeter-plugins.org/downl ...

  4. ios手机竖屏拍照图片旋转90°问题解决方法

    手机拍照会给图片添加一个Orientaion信息(即拍照方向),如下: 用ios手机拍照,系统会给图片加上一个方向的属性, ios相机默认的拍照方向是后摄Home键在右为正,前摄Home键在左为正. ...

  5. Postman 插件安装和使用

    1.google商店 搜索“谷歌访问助手” 2.在商店搜索Postman 3.安装Postman 4.访问chrome://apps/  5.点击postman

  6. 根据motif binding来确定target gene | HOMER | FIMO | MEME

    主流的motif数据库 JASPAR dbcorrdb - SCENIC使用的 TRANSFAC® 7.0 Public 2005 and TRANSCompel 7.0 Public 2005 - ...

  7. 【转】MySQL的安装与配置——详细教程-window系统下

    https://www.cnblogs.com/winton-nfs/p/11524007.html 免安装版的Mysql MySQL关是一种关系数据库管理系统,所使用的 SQL 语言是用于访问数据库 ...

  8. NLP基本模型

    textcnn: 加载预训练词典:https://blog.csdn.net/nlpuser/article/details/83627709 构建textcnn网络:https://blog.csd ...

  9. BicycleGAN: Toward Multimodal Image-to-Image Translation - 1 - 论文学习,成对数据

    Abstract 许多图像到图像的翻译问题是有歧义的,因为一个输入图像可能对应多个可能的输出.在这项工作中,我们的目标是在一个条件生成模型设置中建立可能的输出分布.将模糊度提取到一个低维潜在向量中,在 ...

  10. (.Net) NLog 记录日志功能

    https://codeload.github.com/NLog/NLog/zip/v4.6.6 https://nlog-project.org/?r=redirect Logger logger ...