js ajax同步请求造成浏览器假死的问题
一、问题的起因
今天做一个需求遇到了这么个情况,就是用户个人中心有个功能,点击按钮,可以刷新用户当前的积分,这个肯定需要使用到ajax的同步请求了,当时喀喀喀三下五除二写玩了,大概代码如下:
/**
* 异步当前用户积分 by zgw 20161216
* @return {[type]} [description]
*/
function flushIntegralSum() {
//点击按钮刷新前修改按钮的文案,已经去掉点击事情,防止多次点击
$("#flushbutton").replaceWith('<a style="color:#3fb0ff;font-size:14px;" href="javascript:void(0);" 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);" 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);" 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);" 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 来解决
内容出自:http://www.cnblogs.com/panmy/p/5651732.html
js ajax同步请求造成浏览器假死的问题的更多相关文章
- async:false同步请求,浏览器假死
// 异步请求导致数据错乱 // function get_num(){ // $("input[name='monitor']").eq(1).attr('checked',tr ...
- jQuery Ajax同步参数导致浏览器假死怎么办
俗话说不作死就不会死,今天作死了一回,写了一个比较二逼的函数,遇到了同步Ajax引起的UI线程阻塞问题,在此记录一下. 事情起因是这样的,因为页面上有多个相似的异步请求动作,本着提高代码可重用性的 ...
- (转)优化js脚本设计,防止浏览器假死
在Web开发的时候经常会遇到浏览器不响应事件进入假死状态,甚至弹出“脚本运行时间过长“的提示框,如果出现这种情况说明你的脚本已经失控了,必须进行优化. 为什么会出现这种情况呢,我们先来看一下浏览器的内 ...
- 优化js脚本设计,防止浏览器假死
在Web开发的时候经常会遇到浏览器不响应事件进入假死状态,甚至弹出"脚本运行时间过长"的提示框,如果出现这种情况说明你的脚本已经失控了,必须进行优化. 为什么会出现这种情况呢,我们 ...
- ajax同步请求JS代码
ajax同步请求JS代码 <script type="text/javascript"> var txt = document.getElementById('txt' ...
- setTimeout 导致的浏览器假死
问题 前几天,同事遇到一个浏览器假死的问题.就是浏览器在响应一个请求的时候,就突然不响应时间,进入假死状态,Cup也飙升到100%. 但是这个问题只出现在IE浏览器,chrome和Firefox等 ...
- jQuery Ajax async=>false异步改为同步时,导致浏览器假死的处理方法
今天做一个需求遇到了这么个情况,就是用户个人中心有个功能,点击按钮,可以刷新用户当前的积分,这个肯定需要使用到ajax的同步请求了,当时喀喀喀三下五除二写玩了,大概代码如下: /** * 异步当前用户 ...
- html5 WebWorkers 防止浏览器假死
在Web开发的时候经常会遇到浏览器不响应事件进入假死状态,甚至弹出“脚本运行时间过长“的提示框,如果出现这种情况说明你的脚本已经失控了. 一个浏览器至少存在三个线程:js引擎线程(处理js).GUI渲 ...
- ajax同步请求与异步请求的区别
ajax 区别: async:布尔值,用来说明请求是否为异步模式.async是很重要的,因为它是用来控制JavaScript如何执行该请求. 当设置为true时,将以异步模式发送该请求,JavaScr ...
随机推荐
- tomcat 配置项目指定域名
<Host name="www.xxx.com" appBase="D:/tomcat/webapps/web"> <alias>xxx ...
- ASP.NET Cache缓存的用法
本文导读:在.NET运用中经常用到缓存(Cache)对象.有HttpContext.Current.Cache以及HttpRuntime.Cache,HttpRuntime.Cache是应用程序级别的 ...
- Leetcode Construct Binary Tree from Inorder and Postorder Traversal
Given inorder and postorder traversal of a tree, construct the binary tree. Note:You may assume that ...
- 洛谷 P1204 [USACO1.2]挤牛奶Milking Cows Label:模拟Ex 74分待查
题目描述 三个农民每天清晨5点起床,然后去牛棚给3头牛挤奶.第一个农民在300秒(从5点开始计时)给他的牛挤奶,一直到1000秒.第二个农民在700秒开始,在 1200秒结束.第三个农民在1500秒开 ...
- Redis 配置文件总结
1.1 文件说明 1.1.1 主要文件说明 1 redis-server Redis服务器 2 redis-cli Redis命令行客户端 3 redis-benchemark redis-be ...
- MongoDB命令及SQL语法对比
mongodb与mysql命令对比 传统的关系数据库一般由数据库(database).表(table).记录(record)三个层次概念组成,MongoDB是由数据库(database).集合(col ...
- mysql数据库安装及使用
前言:本文为在ubuntu系统下使用mysql数据库,mysql 版本为:Ver 14.14 Distrib 5.5.43 (mysql版本可在命令行中输入mysql --version显示) 一.m ...
- LinkedList实现队列和堆栈的代码
package 集合; import java.util.LinkedList; /* *队列:先进先出 *把romovelast改成romoveFirst就成了堆栈 先进后出 * * */publ ...
- IBatis按条件分页查询
XML中代码 <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE sqlMap PUBLIC & ...
- bzoj 4445 [SCOI2015] 小凸想跑步
题目大意:一个凸包,随机一个点使得其与前两个点组成的面积比与其他相邻两个点组成的面积小的概率 根据题意列方程,最后求n条直线的交的面积与原凸包面积的比值 #include<bits/stdc++ ...