解决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 各浏览器的 Javascript 效率对比
Jan 23 Javascript
用XMLDOM和ADODB.Stream实现base64编码解码实现代码
Nov 28 Javascript
js中if语句的几种优化代码写法
Mar 12 Javascript
HTML上传控件取消选择
Mar 06 Javascript
随窗体滑动的小插件sticky源码
Jun 21 Javascript
javascript中的this详解
Dec 08 Javascript
jquery使用经验小结
May 20 Javascript
jquery实现顶部向右伸缩的导航区域代码
Sep 02 Javascript
vue-cli之router基本使用方法详解
Oct 17 Javascript
JavaScript中Array方法你该知道的正确打开方法
Sep 11 Javascript
解决ele ui 表格表头太长问题的实现
Nov 13 Javascript
Vue+elementUI实现多图片上传与回显功能(含回显后继续上传或删除)
Mar 23 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
冰滴咖啡制作步骤
2021/03/03 冲泡冲煮
探讨捕获php错误信息方法的详解
2013/06/09 PHP
PHP大批量插入数据库的3种方法和速度对比
2014/07/08 PHP
浅谈使用 PHP 进行手机 APP 开发(API 接口开发)
2014/08/11 PHP
php自动提交表单的方法(基于fsockopen与curl)
2016/05/09 PHP
php下载远程大文件(获取远程文件大小)的实例
2017/06/17 PHP
php利用云片网实现短信验证码功能的示例代码
2017/11/18 PHP
PHP fopen函数用法实例讲解
2019/02/15 PHP
浅谈javascript中的作用域
2012/04/07 Javascript
JS面向对象基础讲解(工厂模式、构造函数模式、原型模式、混合模式、动态原型模式)
2014/08/16 Javascript
javascript二维数组转置实例
2015/01/22 Javascript
学习JavaScript设计模式之代理模式
2016/01/12 Javascript
jQuery复制节点用法示例(clone方法)
2016/09/08 Javascript
JavaScript动态数量的文件上传控件
2016/11/18 Javascript
Vue 2.5 Level E 发布了: 新功能特性一览
2017/10/24 Javascript
微信小程序实现天气预报功能
2018/07/18 Javascript
jQuery实现的响应鼠标移动方向插件用法示例【附源码下载】
2018/08/28 jQuery
使用Vue-cli 中为单独页面设置背景图片铺满全屏
2020/07/17 Javascript
python创建和删除目录的方法
2015/04/29 Python
Python3遍历目录树实现方法
2015/05/22 Python
python写日志文件操作类与应用示例
2019/07/01 Python
python 怎样将dataframe中的字符串日期转化为日期的方法
2019/09/26 Python
python 下 CMake 安装配置 OPENCV 4.1.1的方法
2019/09/30 Python
Python2.7:使用Pyhook模块监听鼠标键盘事件-获取坐标实例
2020/03/14 Python
PyQt使用QPropertyAnimation开发简单动画
2020/04/02 Python
tensorflow 20:搭网络,导出模型,运行模型的实例
2020/05/26 Python
python编程的核心知识点总结
2021/02/08 Python
python 对xml解析的示例
2021/02/27 Python
英国家具、照明、家居用品网上商店:Wayfair.co.uk
2020/02/13 全球购物
链表面试题-一个链表的结点结构
2015/05/04 面试题
手机促销活动方案
2014/02/05 职场文书
学校宣传标语
2014/06/18 职场文书
五四青年节的活动方案
2014/08/20 职场文书
党员先进事迹材料
2014/12/19 职场文书
大学毕业生个人总结
2015/02/28 职场文书
教你怎么用Python生成九宫格照片
2021/05/20 Python