为什么按 setTimeout 拆分的工作负载仍然会冻结浏览器
Why does a workload split up by setTimeout still freeze the browser?
http://jsfiddle.net/Codemonkey/ye5qv/2/
我正在尝试使用 setInterval 编写大型工作负载以重复运行,以便浏览器可以在每次工作迭代之间喘口气。在上面的示例中,我在每个斐波那契计算间隔之间给浏览器 100 毫秒的休息时间,但从调用fib()
到调用回调的那一刻,浏览器仍然被冻结。注意:在我的示例中,fibo函数在文档加载后一秒之前不会调用,因此您可以清楚地看到它冻结了几秒钟
究竟为什么这种方法不起作用,我怎样才能让它工作?或者,还有哪种方法可以达到相同的目标结果?重申一下,使用 setInterval 拆分工作的目标是浏览器在此过程中永远不应该冻结或冻结。
我正在使用 chrome,我主要关注 V8 引擎,但与 x 浏览器兼容的解决方案是一个奖励
问题是你的代码永远不会达到它调用setTimeout
将控制权交还给浏览器的程度。
更改此设置:
for(var i = start; i < i+workload; i++)
自:
for(var i = start; i < start+workload; i++)
由于workload
是一个正数,i < i + workload
永远不会是假的,所以你有一个无限循环。
将控制权交还给浏览器时不必等待 100 毫秒,只需调用 setTimout
就足以使浏览器处理事件,因此您可以使用时间 0:
setTimeout(function() {
processor(start + workload);
}, 0);
演示:http://jsfiddle.net/Guffa/ye5qv/3/
不幸的是,JavaScript 的setInterval
和setTimeout
并不是真正的异步的,所以所有内容仍将在单个线程中运行。这意味着当你的setInterval
回调被调用时,它会在主线程中运行并阻止其他一切的执行。
这是 John Resig 的一篇很棒的文章,详细讨论了这个问题:JavaScript Timers 如何工作。
如果你想要真正的异步JavaScript,你必须使用像Web Workers这样的东西。
正如其他人在这里指出的那样,在您的特定情况下,您实际上在此行上有一个无限循环:
for(var i = start; i < i+workload; i++)
这导致了您的代码:
setTimeout(function() {
processor(start + workload);
}, 100);
永远不要被召唤。请参阅Guffa的出色答案以获取更多信息。
不过,我的其余答案仍然适用 - 如果您尝试做的不仅仅是简单的操作和同时对.gif
进行动画处理,那么如果不使用 Web Workers 之类的东西,您可能仍然会出现冻结或卡顿。
我注意到在您的代码中实际上从未调用过setInterval
,因为在这一行中
for(var i = start; i < i+workload; i++)
条件总是正确的,因为i
总是小于i+workload
,所以它永远不会退出循环。从循环内的函数返回是件好事。
- 为什么继续;语句冻结浏览器
- 循环的Javascript冻结浏览器,没有语法错误
- AJAX 调用在获得响应并成功执行时会冻结浏览器一段时间
- 如何使用 dojo 在不冻结浏览器的情况下下载文件
- 如何在不冻结浏览器的情况下执行大量javascript代码
- AJAX-如何在不冻结浏览器的情况下逐个发出异步请求
- 为什么按 setTimeout 拆分的工作负载仍然会冻结浏览器
- 必应地图通过添加 8000 个图钉来冻结浏览器
- Javascript:尝试在不冻结浏览器的情况下加载高图表
- Javascript拆分冻结浏览器
- 使用高图创建大型热图会冻结浏览器
- Jquery脚本正在冻结浏览器,但正在工作
- JavaScript冻结浏览器
- jquery中的多个Ajax请求会冻结浏览器
- Javascript -更新textarea冻结浏览器选项卡
- JavaScript冻结浏览器
- 而true循环会冻结浏览器的javascript
- Javascript——等待用户交互而不冻结浏览器
- 加载多个TinyMCE实例会冻结浏览器,解决方案
- Javascript代码会冻结浏览器,并且代码只能在firefox中工作