解决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 表单之间的数据传递代码
Dec 04 Javascript
Jquery+ajax请求data显示在GridView上(asp.net)
Aug 27 Javascript
原生js和jquery中有关透明度设置的相关问题
Jan 08 Javascript
jQuery页面加载初始化常用的三种方法
Jun 04 Javascript
JavaScript动态修改弹出窗口大小的方法
Apr 06 Javascript
js中this用法实例详解
May 05 Javascript
Javascript函数的参数
Jul 16 Javascript
jQuery Mobile动态刷新页面样式的实现方法
May 28 Javascript
内容滑动切换效果jquery.hwSlide.js插件封装
Jul 07 Javascript
js实现九宫格拼图小游戏
Feb 13 Javascript
JavaScript异步上传图片文件的实例代码
Jul 04 Javascript
微信开发之企业付款到银行卡接口开发的示例代码
Sep 18 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 中检查或过滤IP地址的实现代码
2011/11/27 PHP
高质量PHP代码的50个实用技巧必备(下)
2016/01/22 PHP
JavaScript 实现模态对话框 源代码大全
2009/05/02 Javascript
JSON 数据格式介绍
2012/01/13 Javascript
JS/jQuery实现默认显示部分文字点击按钮显示全部内容
2013/05/13 Javascript
jquery等宽输出文字插件使用介绍
2013/09/18 Javascript
js实现特定位取反原理及示例
2014/06/30 Javascript
原生javascript实现拖动元素示例代码
2014/09/01 Javascript
7个去伪存真的JavaScript面试题
2016/01/07 Javascript
【经典源码收藏】基于jQuery的项目常见函数封装集合
2016/06/07 Javascript
Javascript获取图片原始宽度和高度的方法详解
2016/09/20 Javascript
js 能实现监听F5页面刷新子iframe 而父页面不刷新的方法
2016/11/09 Javascript
详解AngularJS ui-sref的简单使用
2017/04/24 Javascript
nodejs制作爬虫实现批量下载图片
2017/05/19 NodeJs
js简易版购物车功能
2017/06/17 Javascript
NodeJS链接MySql数据库的操作方法
2017/06/27 NodeJs
原生js实现移动端Touch轮播图的方法步骤
2019/01/03 Javascript
详解vue beforeRouteEnter 异步获取数据给实例问题
2019/08/09 Javascript
详解Golang 与python中的字符串反转
2017/07/21 Python
python实现简易云音乐播放器
2018/01/04 Python
python 拼接文件路径的方法
2018/10/23 Python
对Python3中bytes和HexStr之间的转换详解
2018/12/04 Python
Python获取命令实时输出-原样彩色输出并返回输出结果的示例
2019/07/11 Python
手写一个python迭代器过程详解
2019/08/27 Python
Python生成随机验证码代码实例解析
2020/06/09 Python
党支部公开承诺书
2014/03/28 职场文书
应聘英语教师求职信
2014/04/24 职场文书
学校对教师的评语
2014/04/28 职场文书
细节决定成败演讲稿
2014/05/12 职场文书
北京奥运会口号
2014/06/21 职场文书
2014年度安全生产目标管理责任书
2014/07/25 职场文书
2015年小学财务工作总结
2015/07/20 职场文书
2016开学第一课心得体会
2016/01/23 职场文书
《社戏》教学反思
2016/02/22 职场文书
Python中Numpy和Matplotlib的基本使用指南
2021/11/02 Python
mysql中关键词exists的用法实例详解
2022/06/10 MySQL