解决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 相关文章推荐
28个JS验证函数收集
Mar 02 Javascript
jQuery 表格工具集
Apr 25 Javascript
JS多物体 任意值 链式 缓冲运动
Aug 10 Javascript
前端开发过程中浏览器版本的两种判定方法
Oct 30 Javascript
JS代码随机生成姓名、手机号、身份证号、银行卡号
Apr 27 Javascript
详解AngularJS通过ocLazyLoad实现动态(懒)加载模块和依赖
Mar 01 Javascript
Bootstrap学习笔记之进度条、媒体对象实例详解
Mar 09 Javascript
jQuery实现动态显示select下拉列表数据的方法
Feb 05 jQuery
ES6知识点整理之函数对象参数默认值及其解构应用示例
Apr 17 Javascript
VueJs里利用CryptoJs实现加密及解密的方法示例
Apr 29 Javascript
彻底搞懂并解决vue-cli4中图片显示的问题实现
Aug 31 Javascript
关于vue 项目中浏览器跨域的配置问题
Nov 10 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中4个加速、缓存扩展的区别和选用建议
2014/03/12 PHP
PHP实现股票趋势图和柱形图
2015/02/07 PHP
深入讲解PHP Session及如何保持其不过期的方法
2015/08/18 PHP
JTrackBar水平拖动效果
2007/07/15 Javascript
Autocomplete Textbox Example javascript实现自动完成成功
2007/08/17 Javascript
JavaScript 盒模型 尺寸深入理解
2012/12/31 Javascript
jquery购物车实时结算特效实现思路
2013/09/23 Javascript
escape函数解决js中ajax传递中文出现乱码问题
2014/10/30 Javascript
JS运动框架之分享侧边栏动画实例
2015/03/03 Javascript
javascript页面倒计时实例
2015/07/25 Javascript
node.js入门实例helloworld详解
2015/12/23 Javascript
详解Webwork中Action 调用的方法
2016/02/02 Javascript
jQuery ajax调用后台aspx后台文件的两种常见方法(不是ashx)
2016/06/28 Javascript
Vue-Router进阶之滚动行为详解
2017/09/13 Javascript
vue-router 权限控制的示例代码
2017/09/21 Javascript
通过JavaScript下载文件到本地的方法(单文件)
2019/03/17 Javascript
vue 通过base64实现图片下载功能
2020/12/19 Vue.js
Python获取apk文件URL地址实例
2013/11/01 Python
python itchat实现微信自动回复的示例代码
2017/08/14 Python
Python分布式进程中你会遇到的问题解析
2019/05/28 Python
python multiprocessing模块用法及原理介绍
2019/08/20 Python
解决Tensorboard 不显示计算图graph的问题
2020/02/15 Python
Python Selenium截图功能实现代码
2020/04/26 Python
Django之腾讯云短信的实现
2020/06/12 Python
使用OpenCV实现道路车辆计数的使用方法
2020/07/15 Python
python uuid生成唯一id或str的最简单案例
2021/01/13 Python
解决virtualenv -p python3 venv报错的问题
2021/02/05 Python
使用CSS3在触屏上为按钮实现激活效果
2013/09/27 HTML / CSS
HTML5自定义属性前缀data-及dataset的使用方法(html5 新特性)
2017/08/24 HTML / CSS
Cocopanda波兰:购买化妆品、护肤品、护发和香水
2020/05/25 全球购物
《油菜花开了》教学反思
2014/02/22 职场文书
沙滩主题婚礼活动策划方案
2014/09/15 职场文书
党的群众路线教育实践活动整改落实情况报告
2014/10/28 职场文书
党的群众路线调研报告
2014/11/03 职场文书
用Python实现Newton插值法
2021/04/17 Python
在js中修改html body的样式
2021/11/11 Javascript