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


Posted in Javascript onJanuary 18, 2018

一、问题的起因

今天做一个需求遇到了这么个情况,就是用户个人中心有个功能,点击按钮,可以刷新用户当前的积分,这个肯定需要使用到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 来解决

以上这篇解决js ajax同步请求造成浏览器假死的问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JavaScript入门教程(2) JS基础知识
Jan 31 Javascript
一个简单的js动画效果代码
Jul 20 Javascript
基于jquery DOM写的类似微博发布的效果
Oct 20 Javascript
基于javascript的JSON格式页面展示美化方法
Jul 02 Javascript
JS实现带关闭功能的阿里妈妈网站顶部滑出banner工具条代码
Sep 17 Javascript
详解Document.Cookie
Dec 25 Javascript
JavaScript过滤字符串中的中文与空格方法汇总
Mar 07 Javascript
10分钟掌握XML、JSON及其解析
Dec 06 Javascript
AngularJS的依赖注入实例分析(使用module和injector)
Jan 19 Javascript
获取当前按钮或者html的ID名称实例(推荐)
Jun 23 Javascript
jQuery实现获取选中复选框的值实例详解
Jun 28 jQuery
Vue $mount实战之实现消息弹窗组件
Apr 22 Javascript
js实时监控文本框输入字数的实例代码
Jan 18 #Javascript
JavaScript实现删除数组重复元素的5种常用高效算法总结
Jan 18 #Javascript
react-router4 配合webpack require.ensure 实现异步加载的示例
Jan 18 #Javascript
分享ES6的7个实用技巧
Jan 18 #Javascript
vue 动态修改a标签的样式的方法
Jan 18 #Javascript
详解vue-meta如何让你更优雅的管理头部标签
Jan 18 #Javascript
Nuxt.js踩坑总结分享
Jan 18 #Javascript
You might like
PHP 学习路线与时间表
2010/02/21 PHP
PHP5 的对象赋值机制介绍
2011/08/02 PHP
浅谈ThinkPHP5.0版本和ThinkPHP3.2版本的区别
2017/06/17 PHP
javascript 导出数据到Excel(处理table中的元素)
2009/12/18 Javascript
jQuery效果 slideToggle() 方法(在隐藏和显示之间切换)
2011/06/28 Javascript
Javascript判断图片尺寸大小实例分析
2014/06/16 Javascript
AngularJS身份验证的方法
2016/02/17 Javascript
JQuery控制图片由中心点逐渐放大效果
2016/06/26 Javascript
jQuery实现表格文本框淡入更改值后淡出效果
2016/09/27 Javascript
jQuery插件zTree实现删除树子节点的方法示例
2017/03/08 Javascript
Javascript实现的StopWatch功能示例
2017/06/13 Javascript
JS判断时间段的实现代码
2017/06/14 Javascript
Javascript快速实现浏览器系统通知
2017/08/26 Javascript
关于vuejs中v-if和v-show的区别及v-show不起作用问题
2018/03/26 Javascript
浅谈angularJs函数的使用方法(大小写转换,拷贝,扩充对象)
2018/10/08 Javascript
vue结合element-ui使用示例
2019/01/24 Javascript
vue框架下部署上线后刷新报404问题的解决方案(推荐)
2019/04/03 Javascript
Layui实现数据表格中鼠标悬浮图片放大效果,离开时恢复原图的方法
2019/09/11 Javascript
Vue使用axios引起的后台session不同操作
2020/08/14 Javascript
[01:00]一分钟回顾2018DOTA2亚洲邀请赛现场活动
2018/04/07 DOTA
Python中is与==判断的区别
2017/03/28 Python
python实现批量视频分帧、保存视频帧
2019/05/31 Python
pytorch torch.expand和torch.repeat的区别详解
2019/11/05 Python
解决jupyter notebook 出现In[*]的问题
2020/04/13 Python
python学习将数据写入文件并保存方法
2020/06/07 Python
keras用auc做metrics以及早停实例
2020/07/02 Python
基于Python模拟浏览器发送http请求
2020/11/06 Python
基于CSS3实现的几个小loading效果
2018/09/27 HTML / CSS
HTML5未来发展趋势
2016/02/01 HTML / CSS
Adobe Html5 Extension开发初体验图文教程
2017/11/14 HTML / CSS
AmazeUI 加载进度条的实现示例
2020/08/20 HTML / CSS
某IT外企面试题-二分法求方程!看看大家的C++功底
2015/07/04 面试题
餐饮收银员岗位职责
2014/02/07 职场文书
小学生保护环境倡议书
2014/05/15 职场文书
爱国主义教育基地观后感
2015/06/18 职场文书
使用CSS3实现按钮悬停闪烁动态特效代码
2021/08/30 HTML / CSS