解决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 dom代码应用 简单的相册[firefox only]
Jun 12 Javascript
input 和 textarea 输入框最大文字限制的jquery插件
Oct 27 Javascript
JS中操作JSON总结
Dec 06 Javascript
JQuery中使用ajax传输超大数据的解决方法
Jul 14 Javascript
JavaScript中的Math.atan2()方法使用详解
Jun 15 Javascript
非常实用的12个jquery代码片段
Nov 02 Javascript
浅谈JavaScript中的分支结构
Jul 01 Javascript
详谈vue+webpack解决css引用图片打包后找不到资源文件的问题
Mar 06 Javascript
JavaScript获取移动设备型号的实现代码(JS获取手机型号和系统)
Mar 10 Javascript
vue中过滤器filter的讲解
Jan 21 Javascript
微信自定义分享链接信息(标题,图片和内容)实现过程详解
Sep 04 Javascript
vue如何使用模拟的json数据查看效果
Mar 31 Vue.js
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
Wordpress php 分页代码
2009/10/21 PHP
PHP中使用CURL发送get/post请求上传图片批处理功能
2018/10/15 PHP
yii2的restful api路由实例详解
2019/05/14 PHP
laravel 实现关闭CSRF(全部关闭、部分关闭)
2019/10/21 PHP
javaScript 判断字符串是否为数字的简单方法
2009/07/25 Javascript
JavaScript的eval JSON object问题
2009/11/15 Javascript
JavaScript使用Prototype实现面向对象的方法
2015/04/14 Javascript
jquery操作angularjs对象
2015/06/26 Javascript
window.location.reload 刷新使用分析(去对话框)
2015/11/11 Javascript
jQuery实现的精美平滑二级下拉菜单效果代码
2016/03/28 Javascript
ionic实现带字的toggle滑动组件
2016/08/27 Javascript
BootStrap 图标icon符号图标glyphicons不正常显示的快速解决办法
2016/12/08 Javascript
9种使用Chrome Firefox 自带调试工具调试javascript技巧
2017/12/22 Javascript
原生js实现淘宝放大镜效果
2020/10/28 Javascript
openlayers实现图标拖动获取坐标
2020/09/25 Javascript
在Python的Django框架中调用方法和处理无效变量
2015/07/15 Python
Python中标准模块importlib详解
2017/04/16 Python
Python简单网络编程示例【客户端与服务端】
2017/05/26 Python
在Python 2.7即将停止支持时,我们为你带来了一份python 3.x迁移指南
2018/01/30 Python
Python文件读写常见用法总结
2019/02/22 Python
python3使用matplotlib绘制条形图
2020/03/25 Python
Django forms表单 select下拉框的传值实例
2019/07/19 Python
150行python代码实现贪吃蛇游戏
2020/04/24 Python
HTML5 Canvas draw方法制作动画效果示例
2013/07/11 HTML / CSS
Vince官网:全球著名设计师品牌,休闲而优雅的服饰
2017/01/15 全球购物
Rodd & Gunn澳大利亚官网:新西兰男装品牌
2018/09/25 全球购物
自荐信的禁忌和要点
2013/10/15 职场文书
纺织工程专业个人求职信范文
2014/01/27 职场文书
大学新闻系求职信
2014/06/03 职场文书
体育比赛口号
2014/06/09 职场文书
2014年前台接待工作总结
2014/12/05 职场文书
行政经理岗位职责
2015/04/15 职场文书
读书笔记怎么写
2015/07/01 职场文书
董事长开业致辞
2015/07/29 职场文书
婚前协议书怎么写,才具有法律效力呢 ?
2019/06/28 职场文书
Spring Boot项目如何优雅实现Excel导入与导出功能
2022/06/10 Java/Android