解决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 相关文章推荐
Save a File Using a File Save Dialog Box
Jun 18 Javascript
Asp.net下利用Jquery Ajax实现用户注册检测(验证用户名是否存)
Sep 12 Javascript
Jquery增加鼠标中间功能mousewheel的实例代码
Sep 05 Javascript
jQuery对指定元素中指定字符串进行替换的方法
Mar 17 Javascript
Vue.js使用$.ajax和vue-resource实现OAuth的注册、登录、注销和API调用
May 10 Javascript
vue父子组件的嵌套的示例代码
Sep 08 Javascript
p5.js入门教程和基本形状绘制
Mar 15 Javascript
JSON字符串操作移除空串更改key/value的介绍
Jan 05 Javascript
js根据需要计算数组中重复出现某个元素的个数
Jan 18 Javascript
在layui中使用form表单监听ajax异步验证注册的实例
Sep 03 Javascript
关于在LayUI中使用AJAX提交巨坑记录
Oct 25 Javascript
js刷新页面location.reload()用法详解
Dec 09 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+AJAX实现无刷新注册(带用户名实时检测)
2006/12/02 PHP
php检查页面是否被百度收录
2015/10/28 PHP
PHP preg_match实现正则表达式匹配功能【输出是否匹配及匹配值】
2017/07/19 PHP
Yii 实现数据加密和解密
2021/03/09 PHP
Javascript与flash交互通信基础教程
2008/08/07 Javascript
jquery遍历input取得input的name
2009/04/27 Javascript
JavaScript DOM 学习第九章 选取范围的介绍
2010/02/19 Javascript
jquery.jstree 增加节点的双击事件代码
2010/07/27 Javascript
jQuery的实现原理的模拟代码 -2 数据部分
2010/08/01 Javascript
基于jQuery的淡入淡出可自动切换的幻灯插件打包下载
2010/09/15 Javascript
使用隐藏的new来创建对象
2011/03/29 Javascript
js简易namespace管理器 实例代码
2013/06/21 Javascript
Jquery 获取对象的几种方式介绍
2014/01/17 Javascript
详解JavaScript中getFullYear()方法的使用
2015/06/10 Javascript
基于BootStrap Metronic开发框架经验小结【八】框架功能总体界面介绍
2016/05/12 Javascript
JS实现列表页面隔行变色效果
2017/03/25 Javascript
vue.js实现价格格式化的方法
2017/05/23 Javascript
js Date()日期函数浏览器兼容问题解决方法
2017/09/12 Javascript
JS实现table表格内针对某列内容进行即时搜索筛选功能
2018/05/11 Javascript
webstorm中配置Eslint的两种方式及差异比较详解
2018/10/19 Javascript
react项目如何使用iconfont的方法步骤
2019/03/13 Javascript
echarts大屏字体自适应的方法步骤
2019/07/12 Javascript
js实现鼠标点击飘爱心效果
2020/08/19 Javascript
零基础写python爬虫之HTTP异常处理
2014/11/05 Python
python实现数组插入新元素的方法
2015/05/22 Python
Python中if __name__ == '__main__'作用解析
2015/06/29 Python
pyqt5实现登录界面的模板
2020/05/30 Python
python爬取音频下载的示例代码
2020/10/19 Python
Python urlopen()参数代码示例解析
2020/12/10 Python
Python实现邮件发送的详细设置方法(遇到问题)
2021/01/18 Python
html5 Web SQL Database 之事务处理函数transaction与executeSQL解析
2013/11/07 HTML / CSS
英国在线定制百叶窗网站:Swift Direct Blinds
2020/02/25 全球购物
安全事故检讨书
2014/01/18 职场文书
计算机专业毕业生自荐书
2014/06/02 职场文书
社区学习党的群众路线教育实践活动心得体会
2014/11/03 职场文书
原生JavaScript实现简单五子棋游戏
2021/06/28 Javascript