解决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 相关文章推荐
js本身的局限性 别让javascript做太多事
Mar 23 Javascript
jQuery EasyUI API 中文文档 - TreeGrid 树表格使用介绍
Nov 21 Javascript
JS获取鼠标坐标位置实例分析
Jan 20 Javascript
JS及PHP代码编写八大排序算法
Jul 12 Javascript
HTML页面,测试JS对C函数的调用简单实例
Aug 09 Javascript
JS实现探测网站链接的方法【测试可用】
Nov 08 Javascript
微信小程序 欢迎界面开发的实例详解
Nov 30 Javascript
Angular实现的简单查询天气预报功能示例
Dec 27 Javascript
Bootstrap Fileinput 4.4.7文件上传实例详解
Jul 25 Javascript
vue-i18n结合Element-ui的配置方法
May 20 Javascript
vue-cli或vue项目利用HBuilder打包成移动端app操作
Jul 29 Javascript
使用原生javascript开发计算器实例代码
Feb 21 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
《心理测量者3》剧场版动画预告
2020/03/02 日漫
中篇:安装及配置PHP
2006/12/13 PHP
php中curl和file_get_content的区别
2014/05/10 PHP
PHP获取指定月份第一天和最后一天的方法
2015/07/18 PHP
WordPress开发中用于获取近期文章的PHP函数使用解析
2016/01/05 PHP
Linux下安装Memcached服务器和客户端与PHP使用示例
2019/04/15 PHP
Laravel Eloquent分表方法并使用模型关联的实现
2019/11/25 PHP
关于UTF-8的客户端用AJAX方式获取GB2312的服务器端乱码问题的解决办法
2010/11/30 Javascript
面向对象Javascript核心支持代码分享
2012/05/23 Javascript
JavaScript判断对象是否为数组
2015/12/22 Javascript
javascript数据类型验证方法
2015/12/31 Javascript
不用一句js代码初始化组件
2016/01/27 Javascript
JavaScript数值千分位格式化的两种简单实现方法
2016/08/01 Javascript
javascript判断firebug是否开启的方法
2016/11/23 Javascript
浅谈Express异步进化史
2017/09/09 Javascript
Vue实现内部组件轮播切换效果的示例代码
2018/04/07 Javascript
js中的深浅拷贝问题简析
2019/05/10 Javascript
Vue 请求传公共参数的操作
2020/07/31 Javascript
解决vue自定义指令导致的内存泄漏问题
2020/08/04 Javascript
Python 获取新浪微博的最新公共微博实例分享
2014/07/03 Python
Python中的Matplotlib模块入门教程
2015/04/15 Python
详解python中的 is 操作符
2017/12/26 Python
Python 实现使用dict 创建二维数据、DataFrame
2018/04/13 Python
django admin 后台实现三级联动的示例代码
2018/06/22 Python
决策树剪枝算法的python实现方法详解
2019/09/18 Python
浅谈python 中的 type(), dtype(), astype()的区别
2020/04/09 Python
北京某公司的.net笔试题
2014/03/20 面试题
出纳岗位职责
2013/11/09 职场文书
企划专员岗位职责
2013/12/09 职场文书
优秀员工年终发言演讲稿
2014/01/01 职场文书
2014爱耳日宣传教育活动总结
2014/03/09 职场文书
职工代表大会主持词
2014/04/01 职场文书
党员民主生活会个人整改措施材料
2014/09/16 职场文书
初中生思想道德自我评价
2015/03/09 职场文书
2015年八一建军节慰问信
2015/03/23 职场文书
2016年“6.26”禁毒宣传月系列活动总结
2016/04/05 职场文书