在寻求提高页面性能时,我之前没有提到的一种技术是使用setTimeout来阻止javascript阻止页面的呈现。
例如,假设我们有一个特别耗时的jQuery内联html:
$('input').click(function () {
// Do stuff
});
如果此代码是内联的,那么当jquery忙于将点击处理程序附加到页面上的每个输入时,我们都会阻止感知页面的完成。
生成一个新线程是明智的:
setTimeout(function() {
$('input').click(function () {
// Do stuff
})
}, 100);
我能看到的唯一缺点是用户在附加点击处理程序之前点击元素的可能性更大。但是,这种风险可能是可以接受的,无论如何我们都有一定程度的风险,即使没有setTimeout。
我是对的,还是我错了?
答案 0 :(得分:11)
实际技术是使用时间为0的setTimeout
。
这是因为JavaScript是单线程的。超时不会导致浏览器生成另一个线程,也不保证代码将在指定的时间内执行。但是,代码将在以下两者中执行:
因此,如果时间为0,则调用setTimeout
可被视为临时屈服于浏览器。
这意味着如果你有长时间运行的代码,你可以通过定期屈服setTimeout
来模拟多线程。您的代码可能如下所示:
var batches = [...]; // Some array
var currentBatch = 0;
// Start long-running code, whenever browser is ready
setTimeout(doBatch, 0);
function doBatch() {
if (currentBatch < batches.length) {
// Do stuff with batches[currentBatch]
currentBatch++;
setTimeout(doBatch, 0);
}
}
注意:虽然在some scenarios中了解这种技术很有用,但我非常怀疑在你描述的情况下你需要它(在DOM上准备事件处理程序)。如果性能确实是一个问题,我建议通过调整选择器来寻找改善真实性能的方法。
例如,如果您在页面上只有一个包含<input>
的表单,请为<form>
提供一个ID,然后使用$('#someId input')
。
答案 1 :(得分:3)
setTimeout()
可用于改善“感知”的加载时间 - 但不是您显示它的方式。使用setTimeout()
不会导致代码在单独的线程中运行。相反,setTimeout()
只需将线程返回到浏览器(大约)指定的时间。当你的功能运行时,浏览器会将线程返回到javascript引擎。在javascript中,永远不会有多个线程(除非您使用的是“Web Workers”)。
因此,如果要在计算密集型任务期间使用setTimeout()
来提高性能,则必须将该任务分解为更小的块,并按顺序执行它们,并使用setTimeout()
将它们链接在一起。这样的事情效果很好:
function runTasks( tasks, idx ) {
idx = idx || 0;
tasks[idx++]();
if( idx < tasks.length ) {
setTimeout( function(){ runTasks(tasks, idx); },1);
}
}
runTasks([
function() {
/* do first part */
},
function() {
/* do next part */
},
function() {
/* do final part */
}
]);
注意:
setTimeout()
调用下一个函数。1
。这足以导致 yield ,并且浏览器将在需要时获取线程,或者如果有时间则允许下一个任务继续。如果您认为有需要,可以尝试使用其他值,但通常1
就是您想要的用途。答案 2 :(得分:-1)
你是对的,错过&#34;错过&#34;点击,但超时值很低,很不可能。