解决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 相关文章推荐
jQuery关于导航条背景切换效果实现示例
Sep 04 Javascript
兼容Firefox的Javascript XSLT 处理XML文件
Dec 31 Javascript
最简单的JavaScript验证整数、小数、实数、有效位小数正则表达式
Apr 17 Javascript
JavaScript编写连连看小游戏
Jul 07 Javascript
自己动手写的javascript前端等待控件
Oct 30 Javascript
JS使用JSON作为参数实例分析
Jun 23 Javascript
AngularJS表单详解及示例代码
Aug 17 Javascript
vue.js中proxyTable 转发请求的实现方法
Sep 20 Javascript
加快Vue项目的开发速度的方法
Dec 12 Javascript
jQuery实现获取当前鼠标位置并输出功能示例
Jan 05 jQuery
微信小程序 导入图标实现过程详解
Oct 11 Javascript
解决vuex数据页面刷新后初始化操作
Jul 26 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
天使彦史上最神还原,性别曝光的那一刻,百万网友恋爱了
2020/03/02 国漫
php REMOTE_ADDR之获取访客IP的代码
2008/04/22 PHP
php获取目录所有文件并将结果保存到数组(实例)
2013/10/25 PHP
codeigniter中实现一次性加载多个view的方法
2015/03/20 PHP
php实现文件预览功能
2017/05/23 PHP
谈谈JavaScript中的函数与闭包
2013/04/14 Javascript
jquery validate在ie8下的bug解决方法
2013/11/13 Javascript
js中用window.open()打开多个窗口的name问题
2014/03/13 Javascript
JavaScript实现Java中Map容器的方法
2016/10/09 Javascript
jQuery动态生成Bootstrap表格
2016/11/01 Javascript
JavaScript中String对象的方法介绍
2017/01/04 Javascript
ES6学习教程之对象的扩展详解
2017/05/02 Javascript
基于Cookie常用操作以及属性介绍
2017/09/07 Javascript
Mac 安装 nodejs方法(图文详细步骤)
2017/10/30 NodeJs
使用axios实现上传图片进度条功能
2017/12/21 Javascript
AngularJs分页插件使用详解
2018/06/30 Javascript
nodejs aes 加解密实例
2018/10/10 NodeJs
jQuery选择器选中最后一个元素,倒数第二个元素操作示例
2018/12/10 jQuery
17道题让你彻底理解JS中的类型转换
2019/08/08 Javascript
vue封装swiper代码实例解析
2019/10/08 Javascript
Element的el-tree控件后台数据结构的生成以及方法的抽取
2020/03/05 Javascript
js实现贪吃蛇游戏(简易版)
2020/09/29 Javascript
python中将阿拉伯数字转换成中文的实现代码
2011/05/19 Python
python PyTorch参数初始化和Finetune
2018/02/11 Python
浅谈配置OpenCV3 + Python3的简易方法(macOS)
2018/04/02 Python
Python将文字转成语音并读出来的实例详解
2019/07/15 Python
Python的控制结构之For、While、If循环问题
2020/06/30 Python
python爬虫beautifulsoup解析html方法
2020/12/07 Python
意大利制造的西装、衬衫和针对男士量身定制的服装:Lanieri
2018/04/08 全球购物
全球性的在线商店:Vogca
2019/05/10 全球购物
通用C#笔试题附答案
2016/11/26 面试题
程序员经常用到的UNIX命令
2015/04/13 面试题
群众路线剖析材料
2014/02/02 职场文书
火灾现场处置方案
2014/05/28 职场文书
群众路线四风自我剖析材料
2014/10/08 职场文书
酒店员工手册范本
2015/05/14 职场文书