<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>岁月如歌 &#187; setTimeout</title>
	<atom:link href="http://lifesinger.org/blog/tag/settimeout/feed/" rel="self" type="application/rss+xml" />
	<link>http://lifesinger.org/blog</link>
	<description>关注用户体验、前端开发，记录生活点滴、岁月足迹。</description>
	<lastBuildDate>Wed, 28 Jul 2010 00:40:47 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>onload 和 DOMContentLoaded 的陷阱</title>
		<link>http://lifesinger.org/blog/2009/07/onload-and-domcontentloaded/</link>
		<comments>http://lifesinger.org/blog/2009/07/onload-and-domcontentloaded/#comments</comments>
		<pubDate>Fri, 03 Jul 2009 08:33:35 +0000</pubDate>
		<dc:creator>lifesinger</dc:creator>
				<category><![CDATA[开发]]></category>
		<category><![CDATA[DOMContentLoaded]]></category>
		<category><![CDATA[onload]]></category>
		<category><![CDATA[setTimeout]]></category>

		<guid isPermaLink="false">http://lifesinger.org/blog/?p=1922</guid>
		<description><![CDATA[在正常情况下： window.onload 事件在所有页面元素（包括图片，脚本等）都下载完毕后才会触发。 除了 IE，其它浏览器支持 DOMContentLoaded 事件。当 DOM 内容下载完毕，就会立刻触发。 事件处理器必须在事件触发前注册才有效，否则不会被执行。例子：在 window 已经 load 完成后，再给 window.onload 注册的处理器不会被执行。 针对 IE，有各种模拟 DOMContentLoaded 事件的办法。目前被广泛采纳的方案是判断 document 是否可以滚动（doScroll）。一旦可以滚动，就意味着 DOM Content 已经加载完毕。 下面说两个陷阱： 在 setTimeout 里给 window.onload 添加处理器。这是不可靠的，无法保证添加的处理器一定会执行。是否执行取决于 setTimeout 的延时和页面内容的加载时间。比如： // Test 1. 在 onload 后添加 onload handler setTimeout(function() { onLoad(function() { alert('Test 1: window loaded.'); // 不一定执行 }); }, 20); 在动态加载的 [...]]]></description>
			<content:encoded><![CDATA[<p>在正常情况下：</p>
<ol>
<li>window.onload 事件在所有页面元素（包括图片，脚本等）都下载完毕后才会触发。</li>
<li>除了 IE，其它浏览器支持 DOMContentLoaded 事件。当 DOM 内容下载完毕，就会立刻触发。</li>
<li>事件处理器必须在事件触发前注册才有效，否则不会被执行。例子：在 window 已经 load 完成后，再给 window.onload 注册的处理器不会被执行。</li>
<li>针对 IE，有各种模拟 DOMContentLoaded 事件的办法。目前被广泛采纳的方案是判断 document 是否可以滚动（doScroll）。一旦可以滚动，就意味着 DOM Content 已经加载完毕。</li>
</ol>
<p>下面说两个陷阱<span id="more-1922"></span>：</p>
<ol>
<li>在 setTimeout 里给 window.onload 添加处理器。这是不可靠的，无法保证添加的处理器一定会执行。是否执行取决于 setTimeout 的延时和页面内容的加载时间。比如：
<pre>
// Test 1. 在 onload 后添加 onload handler
setTimeout(function() {
    onLoad(function() {
        alert('Test 1: window loaded.'); // 不一定执行
    });
}, 20);
</pre>
</li>
<li>在动态加载的 script 的 onload 事件里，给 window.DOMContentLoaded 添加处理器。这更不可靠，除了 IE，其它浏览器下根本不会执行。比如：
<pre>
// Test 2. 测试动态添加 script
getScript('http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js', function() {
   alert('Test 2: jQuery loaded.');
    onReady(function() { alert('Test 2: content loaded.'); }); // 不可靠
});
</pre>
</li>
</ol>
<p>测试页面：<a href="http://lifesinger.org/lab/2009/load_test.html">load_test.html</a></p>
<p>最后提一点：从上面的测试页面中可以看出，IE 下模拟 DOMContentLoaded 事件仅仅是模拟，和其它浏览器依旧存在本质上的差异。在 IE 真正原生支持 DOMContentLoaded 前，疯狂使用<code>$(document).ready(...), YAHOO.util.Event.onDOMReady(...)</code>等方法时，依旧需要谨慎，要留意陷阱。</p>
]]></content:encoded>
			<wfw:commentRss>http://lifesinger.org/blog/2009/07/onload-and-domcontentloaded/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>浏览器后退操作时，表单状态的还原</title>
		<link>http://lifesinger.org/blog/2009/06/reset-form-on-back/</link>
		<comments>http://lifesinger.org/blog/2009/06/reset-form-on-back/#comments</comments>
		<pubDate>Fri, 05 Jun 2009 15:33:30 +0000</pubDate>
		<dc:creator>lifesinger</dc:creator>
				<category><![CDATA[开发]]></category>
		<category><![CDATA[backspace]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[form]]></category>
		<category><![CDATA[reset]]></category>
		<category><![CDATA[setTimeout]]></category>

		<guid isPermaLink="false">http://lifesinger.org/blog/?p=1829</guid>
		<description><![CDATA[测试页面：no_autocomplete_test.html 结论： Safari 和 Opera 是两个极端，一个完全还原，一个完全保留。 Firefox 下最简单的办法是设置 autocomplete = &#8216;off&#8217; 属性。 IE 必须在 setTimeout 中还原表单值才有效。 Chrome 除了不支持 onpageshow, 其它表现和 Firefox 一致。 最后胜出的是： 'v' == '\v' &#038;&#038; setTimeout(function() { // reset code }, 0); 同时在 html 中，将要还原的表单元素加上 autocomplete = &#8216;off&#8217; 属性。 最后，忘掉 Opera.]]></description>
			<content:encoded><![CDATA[<p>测试页面：<a href="http://lifesinger.org/lab/2009/no_autocomplete_test.html">no_autocomplete_test.html</a></p>
<p>结论：</p>
<ol>
<li>Safari 和 Opera 是两个极端，一个完全还原，一个完全保留。</li>
<li>Firefox 下最简单的办法是设置 autocomplete = &#8216;off&#8217; 属性。</li>
<li>IE 必须在 setTimeout 中还原表单值才有效。</li>
<li>Chrome 除了不支持 onpageshow, 其它表现和 Firefox 一致。</li>
</ol>
<p>最后胜出的是：</p>
<pre>
'v' == '\v' &#038;&#038; setTimeout(function() {
    // reset code
}, 0);
</pre>
<p>同时在 html 中，将要还原的表单元素加上 autocomplete = &#8216;off&#8217; 属性。<br />
最后，忘掉 Opera.</p>
]]></content:encoded>
			<wfw:commentRss>http://lifesinger.org/blog/2009/06/reset-form-on-back/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>IE下，事件冒泡二三事</title>
		<link>http://lifesinger.org/blog/2009/04/ie-event-bubble/</link>
		<comments>http://lifesinger.org/blog/2009/04/ie-event-bubble/#comments</comments>
		<pubDate>Mon, 20 Apr 2009 15:47:43 +0000</pubDate>
		<dc:creator>lifesinger</dc:creator>
				<category><![CDATA[开发]]></category>
		<category><![CDATA[event]]></category>
		<category><![CDATA[IE]]></category>
		<category><![CDATA[setTimeout]]></category>
		<category><![CDATA[YUI]]></category>

		<guid isPermaLink="false">http://lifesinger.org/blog/?p=1558</guid>
		<description><![CDATA[请先看测试页面：event_bubbling_test.html 结论： IE下，父级容器只接收自身也有的冒泡事件。 IE下，某些事件类型，比如propertychange，不会产生冒泡。 IE下，移除自身的事件，冒泡会被终止。 上一条的解决办法是，将移除自身的操作放在setTimeout里，排队到线程后面。 IE里，setTimeout会改变执行环境，比如Event.getTarget(ev)放在里面将导致错误。 将Event.getTarget(ev)放在setTimeout外面，则一切ok. 总之，IE下，采用父级容器来代理捕捉冒泡事件时，要小心谨慎，多加测试。 附加一点小感慨：阻止链接a的默认事件时，用preventDefault足矣，stopEvent会对之后的扩展带来麻烦。 对于事件代理，可以参阅这篇文章：JavaScript事件代理比你想象中的简单 对于setTimeout，可以看看这篇心得：对How JavaScript Timers Work的理解]]></description>
			<content:encoded><![CDATA[<p>请先看测试页面：<a href="http://lifesinger.org/lab/2009/event_bubbling_test.html">event_bubbling_test.html</a></p>
<h4>结论：</h4>
<ol>
<li>IE下，父级容器只接收自身也有的冒泡事件。</li>
<li>IE下，某些事件类型，比如propertychange，不会产生冒泡。</li>
<li>IE下，移除自身的事件，冒泡会被终止。</li>
<li>上一条的解决办法是，将移除自身的操作放在setTimeout里，排队到线程后面。</li>
<li>IE里，setTimeout会改变执行环境，比如Event.getTarget(ev)放在里面将导致错误。</li>
<li>将Event.getTarget(ev)放在setTimeout外面，则一切ok.</li>
</ol>
<p>总之，IE下，采用父级容器来代理捕捉冒泡事件时，要小心谨慎，多加测试。<br />
附加一点小感慨：阻止链接a的默认事件时，用preventDefault足矣，stopEvent会对之后的扩展带来麻烦。</p>
<p>对于事件代理，可以参阅这篇文章：<a href="http://lifesinger.org/blog/?p=1219">JavaScript事件代理比你想象中的简单</a><br />
对于setTimeout，可以看看这篇心得：<a href="http://lifesinger.org/blog/?p=1184">对How JavaScript Timers Work的理解</a></p>
]]></content:encoded>
			<wfw:commentRss>http://lifesinger.org/blog/2009/04/ie-event-bubble/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>对How JavaScript Timers Work的理解</title>
		<link>http://lifesinger.org/blog/2009/02/john-resig-how-javascript-timers-work/</link>
		<comments>http://lifesinger.org/blog/2009/02/john-resig-how-javascript-timers-work/#comments</comments>
		<pubDate>Sun, 08 Feb 2009 22:07:11 +0000</pubDate>
		<dc:creator>lifesinger</dc:creator>
				<category><![CDATA[开发]]></category>
		<category><![CDATA[animation]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[setInterval]]></category>
		<category><![CDATA[setTimeout]]></category>

		<guid isPermaLink="false">http://lifesinger.org/blog/?p=1184</guid>
		<description><![CDATA[John Resig在How JavaScript Timers Work一文中，对setTimeout和setInterval的分析很精辟： 总结如下： JavaScript engines only have a single thread, forcing asynchronous events to queue waiting for execution. setTimeout and setInterval are fundamentally different in how they execute asynchronous code. If a timer is blocked from immediately executing it will be delayed until the next possible point of execution (which will be [...]]]></description>
			<content:encoded><![CDATA[<p>John Resig在<a href="http://ejohn.org/blog/how-javascript-timers-work/#postcomment">How JavaScript Timers Work</a>一文中，对setTimeout和setInterval的分析很精辟：</p>
<p style="text-align: center"><a href="http://ejohn.org/files/Timers.png"><img title="Timer" src="http://ejohn.org/files/427px-Timers.png" alt="" width="427" height="320" /></a></p>
<p>总结如下：</p>
<ul>
<li>JavaScript engines only have a single thread, forcing asynchronous events to queue waiting for execution.</li>
<li>setTimeout and setInterval are fundamentally different in how they execute asynchronous code.</li>
<li>If a timer is blocked from immediately executing it will be delayed until the next possible point of execution (which will be longer than the desired delay).</li>
<li>Intervals may execute back-to-back with no delay if they take long enough to execute (longer than the specified delay).</li>
</ul>
<p>我的心得：<span id="more-1184"></span></p>
<ol>
<li>无论是setTimeout还是setInterval，触发时，如果当前进程不为空，都得去排队等待执行，这一点上是无差异的。</li>
<li>区别是，setTimeout只需排一次队，setInterval则需要按照预设的间隔时间，每到时间点都去排一下。</li>
<li>setInterval去排队时，如果发现自己还在队列中未执行，则会被drop掉。也就是说，同一个inerval，在队列里只会有一个。</li>
<li>因为队列机制，无论是setTimeout还是setInterval，第一次触发时的时间，只会等于大于预设时间，不可能小于。</li>
<li>对于setInterval来说，如果执行时间大于预设间隔时间，很可能导致连续执行，中间没有时间间隔，这是很糟糕的，很可能会耗费大量cpu.</li>
</ol>
<p>因此，对于动画来说，如果单帧的执行时间大于间隔时间，用setTimeout比用setInterval更保险。John Resig在回复中也表明了这个观点：</p>
<blockquote><p>It really depends on the situation &#8211; and how the timers are actually being used. setInterval will, most likely, get you more &#8216;frames&#8217; in the animation but will certainly tax your processor more. A lot of frameworks end up using setTimeout since it degrades more gracefully on slower computers.</p></blockquote>
<p>一个简单的测试页面：<a href="http://lifesinger.org/lab/2008/timer_test.html">timer_test.html</a>（请在Chrome下运行，注意那些零值或接近零的值，setInterval没有interval了！）</p>
<p>因此，在这种情况下，采用setTimeout更保险：</p>
<pre>
setTimeout(function(){
    /* Some long block of code... */
    setTimeout(arguments.callee, 10);
  }, 10);
</pre>
<p>当然，大部分情况下，单帧执行时间都小于预设的间隔时间，上面分析的差异，是感觉不大出来的。</p>
]]></content:encoded>
			<wfw:commentRss>http://lifesinger.org/blog/2009/02/john-resig-how-javascript-timers-work/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
