jQuery Ajax async=>false异步改为同步时,解决导致浏览器假死的问题


Posted in jQuery onJuly 22, 2019

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

/**
  * 异步当前用户积分 by zgw 20161216
  * @return {[type]} [description]
 */
 function flushIntegralSum() {

 //点击按钮刷新前修改按钮的文案,已经去掉点击事情,防止多次点击
  $("#flushbutton").replaceWith('<a style="color:#3fb0ff;font-size:14px;" href="javascript:void(0);" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" 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);" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" 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);" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" 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);" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" 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异步改为同步时,解决导致浏览器假死的问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

jQuery 相关文章推荐
为JQuery EasyUI 表单组件增加焦点切换功能的方法
Apr 13 jQuery
jQuery ajax调用webservice注意事项
Oct 08 jQuery
原生JS与jQuery编写简单选项卡
Oct 30 jQuery
jQuery实现手机号正则验证输入及自动填充空格功能
Jan 02 jQuery
jQuery中的类名选择器(.class)用法简单示例
May 14 jQuery
js与jQuery实现获取table中的数据并拼成json字符串操作示例
Jul 12 jQuery
jQuery中each遍历的三种方法实例分析
Sep 07 jQuery
JQuery样式操作、click事件以及索引值-选项卡应用示例
May 14 jQuery
基于jquery ajax的多文件上传进度条过程解析
Sep 11 jQuery
jQuery实现图片随机切换、抽奖功能(实例代码)
Oct 23 jQuery
jquery ajax 请求小技巧实例分析
Nov 11 jQuery
jQuery实现高度灵活的表单验证功能示例【无UI】
Apr 30 jQuery
jquery插件开发模式实例详解
Jul 20 #jQuery
jquery实现下载图片功能
Jul 18 #jQuery
jQuery实现图片下载代码
Jul 18 #jQuery
jquery图片预览插件实现方法详解
Jul 18 #jQuery
jquery实现垂直无限轮播的方法分析
Jul 16 #jQuery
JQuery实现简单的复选框树形结构图示例【附源码下载】
Jul 16 #jQuery
jquery实现自定义树形表格的方法【自定义树形结构table】
Jul 12 #jQuery
You might like
星际争霸任务指南——虫族
2020/03/04 星际争霸
人大复印资料处理程序_查询篇
2006/10/09 PHP
Smarty局部缓存的几种方法简介
2014/06/17 PHP
PHP用反撇号执行外部命令
2015/04/14 PHP
php+js实现裁剪任意形状图片
2018/10/31 PHP
(转载)JavaScript中匿名函数,函数直接量和闭包
2007/05/08 Javascript
javascript 网页跳转的方法
2008/12/24 Javascript
JQuery魔力之$(&quot;tagName&quot;)与selector
2012/03/05 Javascript
jQuery实现页面滚动时层智能浮动定位实例探讨
2013/03/29 Javascript
通过pjax实现无刷新翻页(兼容新版jquery)
2014/01/31 Javascript
运用jQuery定时器的原理实现banner图片切换
2014/10/22 Javascript
jQuery获取浏览器类型和版本号的方法
2016/07/05 Javascript
jQuery Easyui使用(二)之可折叠面板动态加载无效果的解决方法
2016/08/17 Javascript
利用AngularJs实现京东首页轮播图效果
2016/09/08 Javascript
基于JavaScript实现百度搜索框效果
2020/06/28 Javascript
vue组件编写之todolist组件实例详解
2018/01/22 Javascript
seajs下require书写约定实例分析
2018/05/16 Javascript
浅谈PDF.js使用心得
2018/06/07 Javascript
jQuery轻量级表单模型验证插件
2018/10/15 jQuery
vue-socket.io跨域问题有效解决方法
2020/02/11 Javascript
原生javascript实现类似vue的数据绑定功能示例【观察者模式】
2020/02/24 Javascript
[04:40]2016个国际邀请赛中国区预选赛场地——华西村观战指南
2016/06/25 DOTA
[01:17:55]VGJ.T vs Mineski 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/20 DOTA
Python 3.x读写csv文件中数字的方法示例
2017/08/29 Python
解决Matplotlib图表不能在Pycharm中显示的问题
2018/05/24 Python
python pandas 如何替换某列的一个值
2018/06/09 Python
在mac下查找python包存放路径site-packages的实现方法
2018/11/06 Python
python hough变换检测直线的实现方法
2019/07/12 Python
TensorFlow dataset.shuffle、batch、repeat的使用详解
2020/01/21 Python
Python连接SQLite数据库并进行增册改查操作方法详解
2020/02/18 Python
Smallable意大利家庭概念店:设计师童装及家居装饰
2018/01/08 全球购物
ProBikeKit德国:在线公路自行车专家
2018/06/03 全球购物
建筑工程技术应届生求职信
2013/11/17 职场文书
员工保密承诺书
2014/05/28 职场文书
超详细Python解释器新手安装教程
2021/05/10 Python
我收到了德劲DE1107
2022/04/05 无线电