setTimeout等你不知道的细节

3 篇文章 0 订阅

setTimeout等你不知道的细节

8.6 Timers
The setTimeout() and setInterval() methods allow authors to schedule timer-based callbacks.

id = self.setTimeout(handler [, timeout [, …arguments ] ])✔MDN
Schedules a timeout to run handler after timeout milliseconds. Any arguments are passed straight through to the handler.

id = self.setTimeout(code [, timeout ])
Schedules a timeout to compile and run code after timeout milliseconds.

self.clearTimeout(id)✔MDN
Cancels the timeout set with setTimeout() or setInterval() identified by id.

id = self.setInterval(handler [, timeout [, …arguments ] ])✔MDN
Schedules a timeout to run handler every timeout milliseconds. Any arguments are passed straight through to the handler.

id = self.setInterval(code [, timeout ])
Schedules a timeout to compile and run code every timeout milliseconds.

self.clearInterval(id)✔MDN
Cancels the timeout set with setInterval() or setTimeout() identified by id.

Timers can be nested; after five such nested timers, however, the interval is forced to be at least four milliseconds.

This API does not guarantee that timers will run exactly on schedule. Delays due to CPU load, other tasks, etc, are to be expected.

Objects that implement the WindowOrWorkerGlobalScope mixin have a map of active timers, which is a map, initially empty. Each key in this map is an identifier for a timer, and each value is a DOMHighResTimeStamp, representing the expiry time for that timer.

For entries put in the map of active timers by the timer initialization steps, i.e., by setTimeout() and setInterval(), the keys are numbers. For other specifications that use the run steps after a timeout algorithm, the identifier is a unique non-numeric value. Only the numeric-keyed timers are affected by clearTimeout() and clearInterval(), but all timers contribute to idle deadline computation, and are cleared when the relevant global is destroyed.

The setTimeout(handler, timeout, …arguments) method steps are to return the result of running the timer initialization steps given this, handler, timeout, arguments, and false.

The setInterval(handler, timeout, …arguments) method steps are to return the result of running the timer initialization steps given this, handler, timeout, arguments, and true.

The clearTimeout(id) and clearInterval(id) method steps are to remove this’s map of active timers[id].

Because clearTimeout() and clearInterval() clear entries from the same map, either method can be used to clear timers created by setTimeout() or setInterval().

The timer initialization steps, given a WindowOrWorkerGlobalScope global, a string or Function handler, a number timeout, a list arguments, a boolean repeat, and optionally (and only if repeat is true) a number previousId, are:

Let thisArg be global if that is a WorkerGlobalScope object; otherwise let thisArg be the WindowProxy that corresponds to global.

If previousId was given, let id be previousId; otherwise, let id be an implementation-defined integer that is greater than zero and does not already exist in global’s map of active timers.

If the surrounding agent’s event loop’s currently running task is a task that was created by this algorithm, then let nesting level be the task’s timer nesting level. Otherwise, let nesting level be zero.

The task’s timer nesting level is used both for nested calls to setTimeout(), and for the repeating timers created by setInterval(). (Or, indeed, for any combination of the two.) In other words, it represents nested invocations of this algorithm, not of a particular method.

If timeout is less than 0, then set timeout to 0.

If nesting level is greater than 5, and timeout is less than 4, then set timeout to 4.

Let callerRealm be the current Realm Record, and calleeRealm be global’s relevant Realm.

Let initiating script be the active script.

Assert: initiating script is not null, since this algorithm is always called from some script.

Let task be a task that runs the following substeps:

If id does not exist in global’s map of active timers, then abort these steps.

If handler is a Function, then invoke handler given arguments with the callback this value set to thisArg. If this throws an exception, catch it, and report the exception.

Otherwise:

Assert: handler is a string.

Perform HostEnsureCanCompileStrings(callerRealm, calleeRealm). If this throws an exception, catch it, report the exception, and abort these steps.

Let settings object be global’s relevant settings object.

Let base URL be initiating script’s base URL.

Assert: base URL is not null, as initiating script is a classic script or a JavaScript module script.

Let fetch options be a script fetch options whose cryptographic nonce is initiating script’s fetch options’s cryptographic nonce, integrity metadata is the empty string, parser metadata is “not-parser-inserted”, credentials mode is initiating script’s fetch options’s credentials mode, and referrer policy is initiating script’s fetch options’s referrer policy.

The effect of these options ensures that the string compilation done by setTimeout() and setInterval() behaves equivalently to that done by eval(). That is, module script fetches via import() will behave the same in both contexts.

Let script be the result of creating a classic script given handler, settings object, base URL, and fetch options.

Run the classic script script.

If id does not exist in global’s map of active timers, then abort these steps.

It might have been removed via the author code in handler calling clearTimeout() or clearInterval().

If repeat is true, then perform the timer initialization steps again, given global, handler, timeout, arguments, true, and id.

Otherwise, remove global’s map of active timers[id].

Increment nesting level by one.

Set task’s timer nesting level to nesting level.

Let completionStep be an algorithm step which queues a global task on the timer task source given global to run task.

Run steps after a timeout given global, “setTimeout/setInterval”, timeout, completionStep, and id.

Return id.

Argument conversion as defined by Web IDL (for example, invoking toString() methods on objects passed as the first argument) happens in the algorithms defined in Web IDL, before this algorithm is invoked.

So for example, the following rather silly code will result in the log containing "ONE TWO ":

var log = ‘’;
function logger(s) { log += s + ’ '; }

setTimeout({ toString: function () {
setTimeout(“logger(‘ONE’)”, 100);
return “logger(‘TWO’)”;
} }, 100);
To run tasks of several milliseconds back to back without any delay, while still yielding back to the browser to avoid starving the user interface (and to avoid the browser killing the script for hogging the CPU), simply queue the next timer before performing work:

function doExpensiveWork() {
var done = false;
// …
// this part of the function takes up to five milliseconds
// set done to true if we’re done
// …
return done;
}

function rescheduleWork() {
var id = setTimeout(rescheduleWork, 0); // preschedule next iteration
if (doExpensiveWork())
clearTimeout(id); // clear the timeout if we don’t need it
}

function scheduleWork() {
setTimeout(rescheduleWork, 0);
}

scheduleWork(); // queues a task to do lots of work
To run steps after a timeout, given a WindowOrWorkerGlobalScope global, a string orderingIdentifier, a number milliseconds, a set of steps completionSteps, and an optional value timerKey:

Assert: if timerKey is given, then the caller of this algorithm is the timer initialization steps. (Other specifications must not pass timerKey.)

If timerKey is not given, then set it to a new unique non-numeric value.

Let startTime be the current high resolution time given global.

Set global’s map of active timers[timerKey] to startTime plus milliseconds.

Run the following steps in parallel:

If global is a Window object, wait until global’s associated Document has been fully active for a further milliseconds milliseconds (not necessarily consecutively).

Otherwise, global is a WorkerGlobalScope object; wait until milliseconds milliseconds have passed with the worker not suspended (not necessarily consecutively).

Wait until any invocations of this algorithm that had the same global and orderingIdentifier, that started before this one, and whose milliseconds is equal to or less than this one’s, have completed.

Optionally, wait a further implementation-defined length of time.

This is intended to allow user agents to pad timeouts as needed to optimize the power usage of the device. For example, some processors have a low-power mode where the granularity of timers is reduced; on such platforms, user agents can slow timers down to fit this schedule instead of requiring the processor to use the more accurate mode with its associated higher power usage.

Perform completionSteps.

If timerKey is a non-numeric value, remove global’s map of active timers[timerKey].

Run steps after a timeout is meant to be used by other specifications that want to execute developer-supplied code after a developer-supplied timeout, in a similar manner to setTimeout(). (Note, however, it does not have the nesting and clamping behavior of setTimeout().) Such specifications can choose an orderingIdentifier to ensure ordering within their specification’s timeouts, while not constraining ordering with respect to other specification’s timeouts.

原链接:原链接(html 标准)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值