diff options
Diffstat (limited to 'files/zh-cn/web/api/window/settimeout/index.html')
-rw-r--r-- | files/zh-cn/web/api/window/settimeout/index.html | 476 |
1 files changed, 0 insertions, 476 deletions
diff --git a/files/zh-cn/web/api/window/settimeout/index.html b/files/zh-cn/web/api/window/settimeout/index.html deleted file mode 100644 index f9813851f7..0000000000 --- a/files/zh-cn/web/api/window/settimeout/index.html +++ /dev/null @@ -1,476 +0,0 @@ ---- -title: window.setTimeout -slug: Web/API/Window/setTimeout -tags: - - Timers - - WindowOrWorkerGlobalScope - - WindowTimers - - setTimeout -translation_of: Web/API/WindowOrWorkerGlobalScope/setTimeout ---- -<p>{{APIRef("HTML DOM")}}</p> - -<p> {{domxref("WindowOrWorkerGlobalScope")}} 混合的 <strong><code>setTimeout()</code></strong>方法设置一个定时器,该定时器在定时器到期后执行一个函数或指定的一段代码。</p> - -<h2 id="Syntax" name="Syntax">语法</h2> - -<pre class="syntaxbox notranslate"><code>var<em> </em>timeoutID = <em>scope</em>.setTimeout(<em>function</em>[<em>,</em> <em>delay, arg1, arg2</em>, ...]); -var timeoutID = <em>scope</em>.setTimeout(function[, <em>delay</em>]); -var<em> </em>timeoutID = <em>scope</em>.setTimeout(<em>code</em>[, <em>delay</em>]);</code></pre> - -<h3 id="参数">参数</h3> - -<dl> - <dt><code>function</code></dt> - <dd>{{jsxref("function")}} 是你想要在到期时间(<code>delay</code>毫秒)之后执行的<a href="https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function" title="en-US/docs/Core_JavaScript_1.5_Reference/Global_Objects/Function">函数</a>。</dd> - <dt><code>code</code></dt> - <dd>这是一个可选语法,你可以使用字符串而不是{{jsxref("function")}} ,在<code>delay</code>毫秒之后编译和执行字符串 (使用该语法是<strong>不推荐的,</strong> 原因和使用 {{jsxref("Global_Objects/eval", "eval()")}}一样,有安全风险)。</dd> - <dt><code>delay</code> {{optional_inline}}</dt> - <dd>延迟的毫秒数 (一秒等于1000毫秒),函数的调用会在该延迟之后发生。如果省略该参数,delay取默认值0,意味着“马上”执行,或者尽快执行。不管是哪种情况,实际的延迟时间可能会比期待的(delay毫秒数) 值长,原因请查看{{anch("实际延时比设定值更久的原因:最小延迟时间")}}。</dd> - <dt><code>arg1, ..., argN</code> {{optional_inline}}</dt> - <dd>附加参数,一旦定时器到期,它们会作为参数传递给{{jsxref("function")}} </dd> -</dl> - -<div class="note"> -<p><strong>备注</strong>:需要注意的是,IE9 及更早的 IE 浏览器不支持向回调函数传递额外参数(第一种语法)。如果你想要在IE中达到同样的功能,你必须使用一种兼容代码 (查看 {{anch("兼容旧环境(polyfill)")}} 一段).</p> -</div> - -<h3 id="Examples" name="Examples">返回值</h3> - -<p>返回值<code>timeoutID</code>是一个正整数,表示定时器的编号。这个值可以传递给{{domxref("WindowOrWorkerGlobalScope.clearTimeout","clearTimeout()")}}来取消该定时器。</p> - -<p>需要注意的是<code>setTimeout()</code>和{{domxref("WindowOrWorkerGlobalScope.setInterval", "setInterval()")}}共用一个编号池,技术上,<code>clearTimeout()</code>和 {{domxref("WindowOrWorkerGlobalScope.clearInterval", "clearInterval()")}} 可以互换。但是,为了避免混淆,不要混用取消定时函数。</p> - -<p>在同一个对象上(一个window或者worker),<code>setTimeout()</code>或者<code>setInterval()</code>在后续的调用不会重用同一个定时器编号。但是不同的对象使用独立的编号池。</p> - -<h2 id="例子">例子</h2> - -<p>下文的例子在网页中设置了两个简单的按钮,以触发 <code>setTimeout()</code> 和 <code>clearTimeout()</code> 方法:按下第一个按钮会设置一个定时器,定时器在 2s 后显示一个警告对话框,并将此次 setTimeout 的定时器 ID 保存起来,按下第二个按钮可以取消定时器。</p> - -<h3 id="HTML" style="line-height: 24px; font-size: 1.71428571428571rem;">HTML</h3> - -<pre class="brush: html notranslate"><p>Live Example</p> -<button onclick="delayedAlert();">Show an alert box after two seconds</button> -<p></p> -<button onclick="clearAlert();">Cancel alert before it happens</button> -</pre> - -<div class="line-number" style="margin-top: 1em; position: absolute; left: 0px; right: 0px; line-height: inherit; top: 0px; background: 0px 0px;"></div> - -<div class="line-number" style="margin-top: 1em; position: absolute; left: 0px; right: 0px; line-height: inherit; top: 19px; background: 0px 0px;"></div> - -<div class="line-number" style="margin-top: 1em; position: absolute; left: 0px; right: 0px; line-height: inherit; top: 38px; background: 0px 0px;"></div> - -<div class="line-number" style="margin-top: 1em; position: absolute; left: 0px; right: 0px; line-height: inherit; top: 57px; background: 0px 0px;"></div> - -<h3 id="JavaScript" style="line-height: 24px; font-size: 1.71428571428571rem;">JavaScript</h3> - -<pre class="brush: js notranslate">var timeoutID; - -function delayedAlert() { - timeoutID = window.setTimeout(slowAlert, 2000); -} - -function slowAlert() { - alert('That was really slow!'); -} - -function clearAlert() { - window.clearTimeout(timeoutID); -} -</pre> - -<div class="line-number" style="margin-top: 1em; position: absolute; left: 0px; right: 0px; line-height: inherit; top: 0px; background: 0px 0px;"></div> - -<div class="line-number" style="margin-top: 1em; position: absolute; left: 0px; right: 0px; line-height: inherit; top: 19px; background: 0px 0px;"></div> - -<div class="line-number" style="margin-top: 1em; position: absolute; left: 0px; right: 0px; line-height: inherit; top: 38px; background: 0px 0px;"></div> - -<div class="line-number" style="margin-top: 1em; position: absolute; left: 0px; right: 0px; line-height: inherit; top: 57px; background: 0px 0px;"></div> - -<div class="line-number" style="margin-top: 1em; position: absolute; left: 0px; right: 0px; line-height: inherit; top: 76px; background: 0px 0px;"></div> - -<div class="line-number" style="margin-top: 1em; position: absolute; left: 0px; right: 0px; line-height: inherit; top: 95px; background: 0px 0px;"></div> - -<div class="line-number" style="margin-top: 1em; position: absolute; left: 0px; right: 0px; line-height: inherit; top: 114px; background: 0px 0px;"></div> - -<div class="line-number" style="margin-top: 1em; position: absolute; left: 0px; right: 0px; line-height: inherit; top: 133px; background: 0px 0px;"></div> - -<div class="line-number" style="margin-top: 1em; position: absolute; left: 0px; right: 0px; line-height: inherit; top: 152px; background: 0px 0px;"></div> - -<div class="line-number" style="margin-top: 1em; position: absolute; left: 0px; right: 0px; line-height: inherit; top: 171px; background: 0px 0px;"></div> - -<div class="line-number" style="margin-top: 1em; position: absolute; left: 0px; right: 0px; line-height: inherit; top: 190px; background: 0px 0px;"></div> - -<div class="line-number" style="margin-top: 1em; position: absolute; left: 0px; right: 0px; line-height: inherit; top: 209px; background: 0px 0px;"></div> - -<div class="line-number" style="margin-top: 1em; position: absolute; left: 0px; right: 0px; line-height: inherit; top: 228px; background: 0px 0px;"></div> - -<h3 id="结果展示">结果展示</h3> - -<p>{{EmbedLiveSample('例子')}}</p> - -<p>也可参考 <a href="/en-US/docs/DOM/window.clearTimeout#Example" title="en-US/docs/DOM/window.clearTimeout#Example"><code>clearTimeout()</code> </a>示例.</p> - -<h2 id="兼容旧环境(polyfill)">兼容旧环境(polyfill)</h2> - -<p>如果你需要向你的回调函数内传递一个或多个参数, 而且还需要兼容那些不支持传递额外参数(不管使用<code>setTimeout()</code> 或者 <code>setInterval()</code>)的浏览器时(比如,IE9及更早的版本), 你可以引入下面的兼容代码来支持向定时器函数传参。将以下代码添加到你代码的最上面:</p> - -<pre class="brush: js notranslate">/*\ -|*| -|*| Polyfill which enables the passage of arbitrary arguments to the -|*| callback functions of JavaScript timers (HTML5 standard syntax). -|*| -|*| https://developer.mozilla.org/en-US/docs/DOM/window.setInterval -|*| -|*| Syntax: -|*| var timeoutID = window.setTimeout(func, delay[, param1, param2, ...]); -|*| var timeoutID = window.setTimeout(code, delay); -|*| var intervalID = window.setInterval(func, delay[, param1, param2, ...]); -|*| var intervalID = window.setInterval(code, delay); -|*| -\*/ - -(function() { - setTimeout(function(arg1) { - if (arg1 === 'test') { - // feature test is passed, no need for polyfill - return; - } - var __nativeST__ = window.setTimeout; - window.setTimeout = function(vCallback, nDelay /*, argumentToPass1, argumentToPass2, etc. */ ) { - var aArgs = Array.prototype.slice.call(arguments, 2); - return __nativeST__(vCallback instanceof Function ? function() { - vCallback.apply(null, aArgs); - } : vCallback, nDelay); - }; - }, 0, 'test'); - - var interval = setInterval(function(arg1) { - clearInterval(interval); - if (arg1 === 'test') { - // feature test is passed, no need for polyfill - return; - } - var __nativeSI__ = window.setInterval; - window.setInterval = function(vCallback, nDelay /*, argumentToPass1, argumentToPass2, etc. */ ) { - var aArgs = Array.prototype.slice.call(arguments, 2); - return __nativeSI__(vCallback instanceof Function ? function() { - vCallback.apply(null, aArgs); - } : vCallback, nDelay); - }; - }, 0, 'test'); -}())</pre> - -<h3 id="针对IE的解决方法">针对IE的解决方法</h3> - -<p>如果你需要单独的针对IE9及之前浏览器的 hack 写法,你可以使用 JavaScript 条件注释:</p> - -<pre class="brush: js notranslate">/*@cc_on - // conditional IE < 9 only fix - @if (@_jscript_version <= 9) - (function(f){ - window.setTimeout = f(window.setTimeout); - window.setInterval = f(window.setInterval); - })(function(f){return function(c,t){var a=[].slice.call(arguments,2);return f(function(){c instanceof Function?c.apply(this,a):eval(c)},t)}}); - @end -@*/</pre> - -<div class="line-number" style="margin-top: 1em; position: absolute; left: 0px; right: 0px; line-height: inherit; top: 0px; background: 0px 0px;"></div> - -<div class="line-number" style="margin-top: 1em; position: absolute; left: 0px; right: 0px; line-height: inherit; top: 19px; background: 0px 0px;"></div> - -<div class="line-number" style="margin-top: 1em; position: absolute; left: 0px; right: 0px; line-height: inherit; top: 38px; background: 0px 0px;"></div> - -<div class="line-number" style="margin-top: 1em; position: absolute; left: 0px; right: 0px; line-height: inherit; top: 57px; background: 0px 0px;"></div> - -<div class="line-number" style="margin-top: 1em; position: absolute; left: 0px; right: 0px; line-height: inherit; top: 76px; background: 0px 0px;"></div> - -<div class="line-number" style="margin-top: 1em; position: absolute; left: 0px; right: 0px; line-height: inherit; top: 95px; background: 0px 0px;"></div> - -<div class="line-number" style="margin-top: 1em; position: absolute; left: 0px; right: 0px; line-height: inherit; top: 114px; background: 0px 0px;"></div> - -<div class="line-number" style="margin-top: 1em; position: absolute; left: 0px; right: 0px; line-height: inherit; top: 133px; background: 0px 0px;"></div> - -<div class="line-number" style="margin-top: 1em; position: absolute; left: 0px; right: 0px; line-height: inherit; top: 152px; background: 0px 0px;"></div> - -<p>或者使用更加清晰的 IE HTML 条件注释:</p> - -<pre class="brush: html notranslate"><!--[if lte IE 9]><script> -(function(f){ -window.setTimeout=f(window.setTimeout); -window.setInterval=f(window.setInterval); -})(function(f){return function(c,t){ -var a=[].slice.call(arguments,2);return f(function(){c instanceof Function?c.apply(this,a):eval(c)},t)} -}); -</script><![endif]--> - - -</pre> - -<div class="line-number" style="margin-top: 1em; position: absolute; left: 0px; right: 0px; line-height: inherit; top: 114px; background: 0px 0px;"></div> - -<div class="line-number" style="margin-top: 1em; position: absolute; left: 0px; right: 0px; line-height: inherit; top: 133px; background: 0px 0px;"></div> - -<h3 id="变通方法">变通方法</h3> - -<p>另一种方法是使用匿名函数包裹你的回调函数,这种方式要消耗更多资源:</p> - -<pre class="brush: js notranslate">var intervalID = setTimeout(function() { myFunc('one', 'two', 'three'); }, 1000); -</pre> - -<div class="line-number" style="margin-top: 1em; position: absolute; left: 0px; right: 0px; line-height: inherit; top: 0px; background: 0px 0px;"></div> - -<p>上面那个例子也可以用<a href="/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions">箭头函数</a>:</p> - -<pre class="brush: js notranslate">var intervalID = setTimeout(() => { myFunc('one', 'two', 'three'); }, 1000); -</pre> - -<p>此外,也可使用 <a href="https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind" title="/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind">function's bind</a>:</p> - -<pre class="brush: js notranslate">setTimeout(function(arg1){}.bind(undefined, 10), 1000); -</pre> - -<h2 id="关于this的问题">关于"<code>this</code>"的问题</h2> - -<p>当你向 <code>setTimeout()</code> (或者其他函数)传递一个函数时,该函数中的<code>this</code>指向跟你的期望可能不同,这个问题在 <a href="/en-US/docs/JavaScript/Reference/Operators/this#Method_binding" title="en-US/docs/Core_JavaScript_1.5_Reference/Operators/Special_Operators/this_Operator#Method_binding">JavaScript reference</a> 中进行了详细解释.</p> - -<h3 id="解释">解释</h3> - -<p>由<code>setTimeout()</code>调用的代码运行在与所在函数完全分离的执行环境上。这会导致,这些代码中包含的 <code>this</code> 关键字在非严格模式会指向 <code>window</code> (或全局)对象,严格模式下为 undefined,这和所期望的<code>this</code>的值是不一样的。</p> - -<div class="note"> -<p>备注:即使是在严格模式下,<code>setTimeout()</code>的回调函数里面的<code>this</code>仍然默认指向<code>window</code>对象, 并不是<code>undefined</code>。</p> -</div> - -<p>查看下面的例子:</p> - -<pre class="brush: js notranslate">let myArray = ["zero", "one", "two"]; -myArray.myMethod = function (sProperty) { - alert(arguments.length > 0 ? this[sProperty] : this); -}; - -myArray.myMethod(); // prints "zero,one,two" -myArray.myMethod(1); // prints "one"</pre> - -<p>上面这段代码正常工作,用<code>myArray</code>调用,在函数内,<code>this[sProperty]</code>等于 <code>myArray[sProperty]</code>。然后,下面这个例子:</p> - -<pre class="brush: js notranslate">setTimeout(myArray.myMethod, 1000); // prints "[object Window]" after 1 second -setTimeout(myArray.myMethod, 1500, "1"); // prints "undefined" after 1.5 seconds</pre> - -<p><code>myArray.myMethod</code>函数传递给 <code>setTimeout</code>,到了定时时间,<code>this</code>没有指向,默认指向<code>window</code>对象。并且没有方法把 <code>thisArg</code> 传递给<code>setTimeout</code>,正如Array方法的<code>forEach</code>,<code>reduce</code>等。下面的例子表示使用<code>call</code>方法设置<code>this</code>也没用。</p> - -<pre class="brush: js notranslate">setTimeout.call(myArray, myArray.myMethod, 2000); // error: "NS_ERROR_XPC_BAD_OP_ON_WN_PROTO: Illegal operation on WrappedNative prototype object" -setTimeout.call(myArray, myArray.myMethod, 2500, 2); // same error</pre> - -<h3 id="可能的解决方案">可能的解决方案</h3> - -<p>一个通用的方法是用包装函数来设置<code>this</code>:</p> - -<pre class="brush: js notranslate">setTimeout(function(){myArray.myMethod()}, 2000); // prints "zero,one,two" after 2 seconds -setTimeout(function(){myArray.myMethod('1')}, 2500); // prints "one" after 2.5 seconds</pre> - -<p>箭头函数也可以:</p> - -<pre class="brush: js notranslate">setTimeout(() => {myArray.myMethod()}, 2000); // prints "zero,one,two" after 2 seconds -setTimeout(() => {myArray.myMethod('1')}, 2500); // prints "one" after 2.5 seconds</pre> - -<p>另一个解决<code>this</code>问题的方法是使用两个非原生的 <code>setTimeout()</code> 和 <code>setInterval()</code> 全局函数代替原生的。该非原生的函数通过使用<a href="/en-US/docs/JavaScript/Reference/Global_Objects/Function/call" title="en-US/docs/JavaScript/Reference/Global_Objects/Function/call"><code>Function.prototype.call</code></a> 方法激活了正确的作用域。下面的代码显示了应该如何替换:</p> - -<pre class="brush: js notranslate">// Enable the passage of the 'this' object through the JavaScript timers - -var __nativeST__ = window.setTimeout, __nativeSI__ = window.setInterval; - -window.setTimeout = function (vCallback, nDelay /*, argumentToPass1, argumentToPass2, etc. */) { - var oThis = this, aArgs = Array.prototype.slice.call(arguments, 2); - return __nativeST__(vCallback instanceof Function ? function () { - vCallback.apply(oThis, aArgs); - } : vCallback, nDelay); -}; - -window.setInterval = function (vCallback, nDelay /*, argumentToPass1, argumentToPass2, etc. */) { - var oThis = this, aArgs = Array.prototype.slice.call(arguments, 2); - return __nativeSI__(vCallback instanceof Function ? function () { - vCallback.apply(oThis, aArgs); - } : vCallback, nDelay); -};</pre> - -<div class="note"><strong>备注:</strong> 这两个替换也让 IE支持了符合 HTML5 标准的定时器函数。所以也能作为一个 polyfills。查看 <a href="#Callback_arguments">Callback arguments</a> 一段.</div> - -<p>新特性检测:</p> - -<pre class="brush: js notranslate">let myArray = ["zero", "one", "two"]; -myArray.myMethod = function (sProperty) { - alert(arguments.length > 0 ? this[sProperty] : this); -}; - -setTimeout(alert, 1500, "Hello world!"); // the standard use of setTimeout and setInterval is preserved, but... -setTimeout.call(myArray, myArray.myMethod, 2000); // prints "zero,one,two" after 2 seconds -setTimeout.call(myArray, myArray.myMethod, 2500, 2); // prints "two" after 2,5 seconds -</pre> - -<p>针对这个问题并没有原生的解决方案。</p> - -<div class="note"><strong>注:</strong>JavaScript 1.8.5 引入了 <code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind" title="en-US/docs/JavaScript/Reference/Global Objects/Function/bind">Function.prototype.bind()</a></code> 方法,该方法允许显式地指定函数调用时 this 所指向的值 。该方法可以帮助你解决 this 指向不确定的问题。</div> - -<p>使用<code>bind()</code>的例子:</p> - -<pre class="brush: js notranslate">let myArray = ['zero', 'one', 'two']; -myBoundMethod = (function (sProperty) { - console.log(arguments.length > 0 ? this[sProperty] : this); -}).bind(myArray); - -myBoundMethod(); // prints "zero,one,two" because 'this' is bound to myArray in the function -myBoundMethod(1); // prints "one" -setTimeout(myBoundMethod, 1000); // still prints "zero,one,two" after 1 second because of the binding -setTimeout(myBoundMethod, 1500, "1"); // prints "one" after 1.5 seconds -</pre> - -<h2 id="备注">备注</h2> - -<p>你可以使用 {{domxref("WindowOrWorkerGlobalScope.clearTimeout()","clearTimeout()")}}来取消定时器。</p> - -<p>如果你希望你的代码被重复的调用 (比如每 N 毫秒一次),考虑使用{{domxref("WindowOrWorkerGlobalScope.setInterval()","setInterval()")}}。</p> - -<h3 id="传递字符串字面量">传递字符串字面量</h3> - -<p>向<code>setTimeout()</code>传递一个字符串而不是函数会遭受到与使用<code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/eval#Don.27t_use_eval.21" title="https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/eval">eval</a></code>一样的风险.</p> - -<pre class="brush: js notranslate">// 推荐 -window.setTimeout(function() { - alert("Hello World!"); -}, 500); - -// 不推荐 -window.setTimeout("alert(\"Hello World!\");", 500); - -</pre> - -<p>字符串会在全局作用域内被解释执行,所以当<code>setTimeout()</code>函数执行完毕后,字符串中的变量不可用.</p> - -<h3 id="实际延时比设定值更久的原因:最小延迟时间">实际延时比设定值更久的原因:最小延迟时间</h3> - -<p>有很多因素会导致setTimeout的回调函数执行比设定的预期值更久,本节将讨论最常见的原因。</p> - -<h4 id="最小延时_>4ms">最小延时 >=4ms</h4> - -<p>在浏览器中,<code>setTimeout()/</code>{{domxref("WindowOrworkerGlobalScope.setInterval","setInterval()")}} 的每调用一次定时器的最小间隔是4ms,这通常是由于函数嵌套导致(嵌套层级达到一定深度),或者是由于已经执行的setInterval的回调函数阻塞导致的。例如:</p> - -<pre class="brush: js notranslate" id="ct-0"><code>function cb() { f(); setTimeout(cb, 0); } -setTimeout(cb, 0);</code></pre> - -<pre class="brush: js notranslate"><code>setInterval(f, 0);</code></pre> - -<p>在Chrome 和 Firefox中, 定时器的第5次调用被阻塞了;在Safari是在第6次;Edge是在第3次。Gecko 从这个版本 <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Releases/56">version 56</a>开始对 <code>setInterval()</code> 开始采用这样的机制(<code>setTimeout()</code>已经实现,具体请参考以下内容)。</p> - -<p>一直以来,不同浏览器中出现这种最小延迟的情况有所不同(例如Firefox) - 从其他地方调用了setInterval( ),或者在嵌套函数调用setTimeout( ) 时(嵌套级别达到特定深度时),都会出现超时延迟。</p> - -<p>如果想在浏览器中实现0ms延时的定时器,你可以参考<a href="http://dbaron.org/log/20100309-faster-timeouts">这里</a>所说的{domxref("window.postMessage()")}}</p> - -<div class="note"> -<p><strong>Note</strong>: 最小延时, <code>DOM_MIN_TIMEOUT_VALUE</code>, 是4ms (但在Firefox中通常是是存储在 <code>dom.min_timeout_value </code>这个变量中), <code>DOM_CLAMP_TIMEOUT_NESTING_LEVEL</code> 的第5层.</p> -</div> - -<div class="note"> -<p><strong>Note</strong>: 4 ms 是在 <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#timers">HTML5 spec </a> 中精确的,并且在2010年及以后的跨浏览器中保持了一致,这个数值比 {{geckoRelease("5.0")}}规定的嵌套函数的最小延时10ms更为精确。</p> -</div> - -<h4 id="未被激活的tabs的定时最小延迟>1000ms">未被激活的tabs的定时最小延迟>=1000ms</h4> - -<p>为了优化后台tab的加载损耗(以及降低耗电量),在未被激活的tab中定时器的最小延时限制为1S(1000ms)。</p> - -<p>Firefox 从version 5 (see {{bug(633421)}}开始采取这种机制,1000ms的间隔值可以通过 <code>dom.min_background_timeout_value</code> 改变。Chrome 从 version 11 (<a href="http://crbug.com/66078">crbug.com/66078</a>)开始采用。</p> - -<p>Android 版的Firefox对未被激活的后台tabs的使用了15min的最小延迟间隔时间 ,并且这些tabs也能完全不被加载。</p> - -<div class="note"> -<p>当 Web Audio API {{domxref("AudioContext")}} 正在被用来播放音频的时候,Firefox 50不会再限制后台tabs的加载。 后续的Firefox 51 版本修正了这个问题,即使在没有音频播放的情况下,也不再限制后台tabs的加载。这个解决了一些软件应用在后台tabs中播放基于文本的音频( note-based) 时,无法去同步音频和画面的问题。</p> -</div> - -<h4 id="追踪型脚本的最小延时限制">追踪型脚本的最小延时限制</h4> - -<p>从Firefox 55版本开始,追踪型脚本(例如 谷歌分析,或者其他的一些被Firefox 的 <a href="https://wiki.mozilla.org/Security/Tracking_protection#Lists">TP lists</a> 识别为追踪型脚本的 外链URL脚本)是重点限制加载的对象。在当前正在使用的页面中,这个节流限制的延时依然是4ms。但是在后台tabs中,这个最小延时限制是10000ms(10s),这个限制会在文档第一次加载后的30s后生效。</p> - -<p>控制这些行为的属性包含以下这些:</p> - -<ul> - <li><code>dom.min_tracking_timeout_value</code>: 4</li> - <li><code>dom.min_tracking_background_timeout_value</code>: 10000</li> - <li><code>dom.timeout.tracking_throttling_delay</code>: 30000</li> -</ul> - -<h4 id="超时延迟">超时延迟</h4> - -<p>除了"最小延时"之外,定时器仍然有可能因为当前页面(或者操作系统/浏览器本身)被其他任务占用导致延时。 需要被强调是, 直到调用 <code>setTimeout()</code>的主线程执行完其他任务之后,回调函数和代码段才能被执行。例如:</p> - -<pre class="notranslate"><code>function foo() { - console.log('foo has been called'); -} -setTimeout(foo, 0); -console.log('After setTimeout');</code></pre> - -<p>会在控制台输出:</p> - -<pre class="notranslate"><code>After setTimeout -foo has been called</code></pre> - -<p>出现这个结果的原因是,尽管<code>setTimeout</code> 以0ms的延迟来调用函数,但这个任务已经被放入了队列中并且等待下一次执行;并不是立即执行;队列中的等待函数被调用之前,当前代码必须全部运行完毕,因此这里运行结果并非预想的那样。</p> - -<h3 id="WebExtension_Background_pages和定时器">WebExtension Background pages和定时器</h3> - -<p>在 <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions">WebExtension</a> 中 background pages,timers工作不正常。这主要因为background pages实际上,并不是一次性全部加载:如果浏览器没有使用它,就不加载,如果需要就恢复。这对于WebExtension是透明的,但是有些事件(包括JS的timers)不会在不加载/恢复循环中执行,所以WebExtension中建议使用alarms。更详细的细节在<a href="https://developer.chrome.com/extensions/background_migration">合并到事件驱动后台脚本</a>。</p> - -<p>在本文写作的时候,只有Chrome展示了如上的特性 — Firefox没有未加载/恢复循环的行为,所以timers仍然可以工作。但是,仍然建议不要在WebExtension中使用timers:</p> - -<p>1.兼容Chorme。</p> - -<p>2.未来行为的改变会引起问题。</p> - -<h3 id="最大延时值">最大延时值</h3> - -<p>包括 IE, Chrome, Safari, Firefox 在内的浏览器其内部以32位带符号整数存储延时。这就会导致如果一个延时(delay)大于 2147483647 毫秒 (大约24.8 天)时就会溢出,导致定时器将会被立即执行。</p> - -<h2 id="规范">规范</h2> - -<table class="standard-table"> - <thead> - <tr> - <th scope="col">Specification</th> - <th scope="col">Status</th> - <th scope="col">Comment</th> - </tr> - </thead> - <tbody> - <tr> - <td>{{SpecName('HTML WHATWG', 'webappapis.html#dom-settimeout', 'WindowOrWorkerGlobalScope.setTimeout()')}}</td> - <td>{{Spec2("HTML WHATWG")}}</td> - <td>Method moved to the <code>WindowOrWorkerGlobalScope</code> mixin in the latest spec.</td> - </tr> - <tr> - <td>{{SpecName("HTML WHATWG", "webappapis.html#dom-settimeout", "WindowTimers.setTimeout()")}}</td> - <td>{{Spec2("HTML WHATWG")}}</td> - <td>Initial definition (DOM Level 0)</td> - </tr> - </tbody> -</table> - -<h2 id="浏览器兼容性">浏览器兼容性</h2> - -<div id="compat-desktop"> -<div class="hidden"> -<p>The compatibility table on this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p> -</div> - -<p>{{Compat("api.WindowOrWorkerGlobalScope.setTimeout")}}</p> -</div> - -<h2 id="See_also" name="See_also" style="margin-bottom: 20px; line-height: 30px; font-size: 2.14285714285714rem;">相关链接:</h2> - -<ul> - <li><a href="https://developer.mozilla.org/en-US/docs/JavaScript/Timers" title="/en-US/docs/JavaScript/Timers">JavaScript timers</a></li> - <li><a href="https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/Timer.jsm" title="/en-US/docs/Mozilla/JavaScript_code_modules/Timer.jsm">Timer.jsm</a></li> - <li>{{domxref("WindowOrWorkerGlobalScope.clearTimeout")}}</li> - <li>{{domxref("WindowTimers.setInterval")}}</li> - <li>{{domxref("window.requestAnimationFrame")}}</li> - <li><a href="https://developer.mozilla.org/en-US/docs/JavaScript/Timers/Daemons" title="/en-US/docs/JavaScript/Timers/Daemons"><em>Daemons</em> management</a></li> -</ul> |