【问题标题】:Browser time takes less than 4 milliseconds to execute setTimeout() for first few times前几次执行 setTimeout() 的浏览器时间不到 4 毫秒
【发布时间】:2019-10-09 17:29:28
【问题描述】:

在从“You Don't Know JS”学习异步和性能时,我尝试了这个小代码 sn-p:

var t = [];
var c = 1;

function foo() {
  t.push((performance.now()).toString());
  if (c < 50) {
    setTimeout(foo, 0);
    c++;
  }
}

最初几次浏览器(我使用的是 chrome)调用 foo 的时间少于 4ms。后来它只花了一点点时间4ms

.

我想问,尽管在创建任务时是 setTimeout(),为什么它在前 3-4 次表现得像微任务?

请帮帮我, 谢谢。

【问题讨论】:

  • “微任务”是什么意思?事实上,我一般不太明白你的问题。您只是在运行一个异步函数,它将在下一个事件周期中执行。
  • 时间差的小可能有多种原因,因为JS是在浏览器中执行的,浏览器自己完成的所有操作、后台调用、缓存等都会影响结果。
  • 在 javascript 微任务中是在不到 4ms 的时间内执行的任务,而不是进入下一个事件周期。例如promise.then() 是微任务。
  • 微任务是一个概念,它们不依赖于特定的执行时间长度(即仅仅因为它低于 4 毫秒并不使其成为微任务)。具体来说,微任务是属于作业队列而不是常规调用堆栈的任何内容:flaviocopes.com/javascript-event-loop/#es6-job-queue
  • 如果您使用setTimeout(fn, 0) 来避免堆栈溢出,请参阅this Q&A

标签: javascript performance asynchronous settimeout performance-testing


【解决方案1】:

为了回答这个问题,setTimeout() 是使用the message queue 的一个示例。微任务是在每个函数运行之后、消息队列启动之前发生的任何事情。微任务队列实际上是 es6 job queue,但自从 v8 之后,它被赋予了新名称。

仅仅因为4ms 下的任务并不能使它成为微任务。我有一个例子,第二个样本采用5ms

您发现有趣趋势的原因很可能是 Chrome 优化。最初的几个调用几乎是立即完成的,随着调用堆栈变长,它会越挖越深以获取更多 RAM。

if (c < 50) {
  setTimeout(foo, 10);
  c++;
}

如果您尝试上述 sn-p,您会发现时间戳更加一致。这是因为调用堆栈以更规律的间隔被添加。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-26
    • 1970-01-01
    • 1970-01-01
    • 2014-05-22
    • 1970-01-01
    • 1970-01-01
    • 2020-11-23
    • 1970-01-01
    相关资源
    最近更新 更多