首页 > 编程语言 >why is the setInterval task executed slower than the setTimeout task in the browser javascript envir

why is the setInterval task executed slower than the setTimeout task in the browser javascript envir

时间:2023-03-02 15:12:28浏览次数:57  
标签:executed slower level setInterval task let nesting setTimeout

why is the setInterval task executed slower than the setTimeout task in the browser javascript environment?

为什么在浏览器 javascript 环境下 setInterval 任务执行速度比 setTimeout 任务慢?

setTimeout(() => {
  console.log(`4`);
});

let id = setInterval(() => {
  console.log(`5`);
  clearInterval(id);
});

Promise.resolve().then(() => console.log(`2`));

queueMicrotask(() => {
  console.log(`3`);
});

console.log(`1`);

/*

1
2

3
4
5

*/

image

setTimeout 定时器时间不准确 bug ❌

let startTime = new Date();
setTimeout(() => {
  let endTime = new Date();
  console.log(endTime - startTime);
}, 0);
for (let i = 0; i < 10**6; i++) {
   // 任务中的同步代码执行时间过长,导致异步宏任务 setTimeout 的执行时间延后 bug
}

HTML Standard

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.
此 API 不保证计时器将完全按计划运行。
由于 CPU 负载、其他任务等导致的延迟是可以预料的。

https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timers

The timer initialization steps
定时器初始化步骤

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.

任务的计时器嵌套级别既用于对 setTimeout() 的嵌套调用,也用于由 setInterval() 创建的重复计时器。 (或者,实际上,对于两者的任意组合。)换句话说,它表示此算法的嵌套调用,而不是特定方法的嵌套调用。

  1. Let thisArg be global if that is a WorkerGlobalScope object; otherwise let thisArg be the WindowProxy that corresponds to global.
  2. 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.
  3. 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.
  4. If timeout is less than 0, then set timeout to 0.
  5. If nesting level is greater than 5, and timeout is less than 4, then set timeout to 4.
  6. Let realm be global's relevant realm.
  7. Let initiating script be the active script.
  8. Assert: initiating script is not null, since this algorithm is always called from some script.
  9. Let task be a task that runs the following substeps:

image

  1. Increment nesting level by one.
  2. Set task's timer nesting level to nesting level.
  3. Let completionStep be an algorithm step which queues a global task on the timer task source given global to run task.
  4. Run steps after a timeout given global, "setTimeout/setInterval", timeout, completionStep, and id.
  5. Return id.

https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-settimeout

使用 requestAnimationFrame 获取更可靠的定时器`时间

// 16ms

https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame

js 获取时间戳差值的小技巧

let startTime = new Date();

let endTime = new Date();

console.log(endTime - startTime);
// 7513

startTime;
// Thu Mar 02 2023 14:27:16 GMT+0800 (China Standard Time)
startTime - 0;
// 1677738436958

endTime;
// Thu Mar 02 2023 14:27:24 GMT+0800 (China Standard Time)
endTime - 0;
// 1677738444471

endTime - startTime;
// 7513

(

标签:executed,slower,level,setInterval,task,let,nesting,setTimeout
From: https://www.cnblogs.com/xgqfrms/p/17171808.html

相关文章