如何解决ajax同步时页面假死的问题?

有一个ajax因为业务需求必须是同步的,不过ajax结果返回前,因为UI线程和JS线程互斥页面会卡死一短时间,求决绝方案。这里简单写了一个小demo演示一下原理

<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<body>
    <button id="button" onclick="console.log('1')">按钮<button>
</body>
</html>
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript">
var fn1 = function(content){
    var t1 = new Date().getTime()
    console.log("fn1: " + "开始" );
    while(new Date().getTime()-t1 < 10000){

    }
    console.log("fn1: " +  "结束"  );
}
fn1();
</script>

在这个demo里,页面打印“开始”和“结束”期间按钮要可以输出 “1”,请问有解决方案吗?

阅读 6.7k
5 个回答

首先

有一个ajax因为业务需求必须是同步的

这个限定本身应该是可以去掉的,没人会让用户的页面卡着不动导致用户很不爽然后关掉你的网页再也不想开这个网站。同步可以用回调解决,不妨说说你为什么等ajax结果的时候要阻塞整个线程,该不会是你不知道可以写个回调然后自己用while轮询了吧?

然后,如果一定要在给定的限制下实现“输出1”,就得在你阻塞整个线程的地方添加代码,允许执行其它代码,相当于自己实现一个非常小的调度算法。鉴于浏览器里没有类似sleep的函数,你的“同步”我可以肯定是用循环实现的,即轮询忙等待,这样不仅用户体验极差,还会占满一个CPU核心。如果不改掉这个循环,为了达到目的,就得每趟循环都额外查看是否有新任务可以执行,有则取出一个任务执行,然后继续循环。你大概是想显示进度条吧,那就直接在循环里更新进度就行了,边检查ajax是否完成边更新进度。

但最好的方法就是去掉你这个奇怪的限制,需要你提供跟你业务相关的信息。

js是单线程的,你阻塞掉,不能干别的,当然卡死了,用异步回调吧

不推荐同步 但是非要用的话就只能做其他优化了
1.页面给出提示
2.优化请求 短时间的卡死应该是可以接受或不感知的

我猜想你是必须等待服务器确认之后才能进行下一步的操作(比如支付等)
若你服务器反应时间过长 可使用请求生成任务id 再使用任务id去查询任务是否完成

javascript本身就是单线程的,要一步一步的执行,ajax出现的意义在于异步调用,局部刷新,这样可以节约时间,提升用户体验,如果想解决假死的问题同时还要强调同步,这个问题就不能解决了
但是很多的时候我们是在数据返回的时候才调用UI去渲染,也就是在success中去渲染UI,在此之前我们用loading小动画,提升用户体验

怎么说呢,我觉得这不是个技术问题,这应该是一个产品问题。
用户觉得卡,或者说在用户体验的角度上、页面没有响应,归根究底,是由于页面没有及时对用户的操作进行有效的反馈。打个比方,在电脑上移动一个大文件,那么不管windows还是macos,都会在移动时显示个“正在移动”或者类似的状态提示,那么用户就会知道,哦,正干活呢,一切正常。假如没有这个提示,用户做完操作,风平浪静,文件也没过去,用户能怎么想?电脑“卡”死了。
回到问题,我觉得如果这个Ajax的结果是极大影响视图层的,那你搞个遮罩把视图层隐藏掉就行,体验好点可以再加个“正在加载请稍后”的提示,和取消按钮,犯不上为了这个把异步都废掉(本来js里也没同步,所以实现方式就只能是阻塞式的)。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题