Javascript:如何在执行 javascript 代码之间设置一个简单的延迟?
Posted
技术标签:
【中文标题】Javascript:如何在执行 javascript 代码之间设置一个简单的延迟?【英文标题】:Javascript: How to put a simple delay in between execution of javascript code? 【发布时间】:2011-06-22 05:02:28 【问题描述】:我有一个 for 循环,它在 javascript 代码中迭代超过 10,000 次。 for 循环创建 标签并将其添加到当前页面 DOM 中的框中。
for(i = 0; i < data.length; i++)
tmpContainer += '<div> '+data[i]+' </div>';
if(i % 50 == 0) /* some delay function */
containerObj.innerhtml = tmpContainer;
我想在每 50 个 标签之后放一个延迟,那么该位置的代码是什么
/* some delay function */
因为加载所有 10,000 个
标签需要花费太多时间。我想以 50 个 标签块的形式更新该框。提前致谢。
【问题讨论】:
【参考方案1】:您可以使用window.setTimeout 函数来延迟某些代码的执行:
if(i % 50 == 0)
window.setTimeout(function()
// this will execute 1 second later
, 1000);
但您的 javascript 将继续执行。它不会停止。
【讨论】:
【参考方案2】:在这些情况下有一个方便的技巧:使用 0 毫秒的 setTimeout。这将导致您的 JavaScript 屈服于浏览器(因此它可以执行其渲染、响应用户输入等),但不会强制它等待一定的时间:
for (i=0;i<data.length;i++)
tmpContainer += '<div> '+data[i]+' </div>';
if (i % 50 == 0 || i == data.length - 1)
(function (html) // Create closure to preserve value of tmpContainer
setTimeout(function ()
// Add to document using html, rather than tmpContainer
, 0); // 0 milliseconds
)(tmpContainer);
tmpContainer = ""; // "flush" the buffer
注意:T.J. Crowder 在下面正确地提到,上面的代码将在循环的每次迭代中创建不必要的函数(一个用于设置闭包,另一个作为setTimeout
的参数)。这不太可能成为问题,但如果您愿意,可以查看 his alternative,它只创建一次闭包函数。
警告:尽管上面的代码会提供更愉快的渲染体验,但不建议在页面上使用 10000 个标签。在此之后,其他所有 DOM 操作都会变慢,因为要遍历的元素更多,而且对布局的任何更改都会进行更昂贵的回流计算。
【讨论】:
可以,但有两个 cmets: 1. 每次达到 50 个 div 时,它都会不必要地创建一个 new 函数。那是 199 个不必要的功能。可能没问题,但仍然可以避免。 2. 将 HTML 构建成一个字符串数组,然后在完成后使用a.join("")
创建一个大字符串,而不是使用字符串连接来构建 HTML。
@T.J.你对这两点都是正确的,但为了简单起见,我没有打扰:1.函数创建很少是性能问题,特别是当你的瓶颈是 DOM 时,2.字符串连接只是 IE 上的问题,并且在其他浏览器中通常更快,但即使对于 IE,由于我将 tmpContainer
重置为空字符串,字符串永远不会变大;)
@Box9:刚看到:document.write
?!?!那绝对行不通。 appendChild
等都可以。
@T.J.好吧,它会工作,但它只会覆盖您拥有的页面,所以它可能不会按预期工作 ;) 我希望很清楚它只是表明使用变量html
而不是tmpContainer
。
@Box9:对“工作”的有趣解释。 ;-) 我会将其删除,因为它完全具有误导性,并附上评论“在此处使用 html
创建元素”。顺便说一句,我之前错了,它是大约 398 个完全不必要的函数(你正在重新创建 创建 闭包的东西,比另一个更不需要)。此外,除非发生data.length % 50 == 0
,否则这将无法输出最后的 1-49,或者至少需要重复的代码才能这样做。取而代之的是:pastie.org/1533736 这是全部,只是为了给出一个好的答案,而不是给你带来困难。【参考方案3】:
我会将创建div
s 的代码分解为一个函数,然后通过setTimeout
定期安排该函数的执行,如下所示:
function createThousands(data)
var index;
index = 0;
doAChunk();
function doAChunk()
var counter;
for (counter = 50; counter > 0; --counter)
// Are we done?
if (index >= data.length)
// Yup
return;
// ...create a div...
// Move to the next
++index;
// Schedule the next pass
setTimeout(doAChunk, 0); // 0 = defer to the browser but come back ASAP
这使用单个闭包doAChunk
来完成工作。一旦其工作完成,该闭包就有资格进行垃圾收集。 (更多:Closures are not complicated)
Live example
【讨论】:
@fehergeri:我的问题?嗯? @fehergeri:哦,我明白了,你的意思是他的问题。我正在处理不进行临时更新的问题;回流完全是另一回事。【参考方案4】:需要很多时间,因为回流。您应该创建一个文档片段,然后添加小子。
When does reflow happen in a DOM environment?
Javascript Performance - Dom Reflow - Google Article
睡觉不能解决你的问题
另一方面,您创建了一个包含innerhtml 和添加到innerhtml 的字符串。字符串的东西真的不需要很大的性能,但是当你执行.innerhtml
命令时,它会启动一个进程,解析你的字符串并创建元素并附加它们。你不能打断或增加延迟。
innerhtml 进程不能休眠或中断。
你需要一个一个生成元素,添加50个元素后,创建一个settimeout延迟。
var frag = document.createDocumentFragment();
function addelements()
var e;
for(i=0;i<50;++i)
e = document.createElement('div');
frag.appendChild(e);
dest.appendChild(frag);
window.setTimeout(addelements,1000);
【讨论】:
【参考方案5】:这是在不挂起浏览器的情况下延迟 javascript 的真正技巧。 您需要使用带有同步方法的 ajax 函数,该函数将调用 php 页面,并且在该 php 页面中您可以使用 sleep() php 函数! http://www.hklabs.org/articles/put-delay-in-javascript
【讨论】:
请注意 link-only answers 是不鼓励的,所以答案应该是寻找解决方案的终点(而不是另一个参考中途停留,随着时间的推移往往会变得陈旧)。请考虑在此处添加独立的概要,并保留链接作为参考。以上是关于Javascript:如何在执行 javascript 代码之间设置一个简单的延迟?的主要内容,如果未能解决你的问题,请参考以下文章