【问题标题】:setTimeout timer eventsetTimeout 定时器事件
【发布时间】:2015-11-06 03:29:09
【问题描述】:
function waitForThreeSeconds(){
    setTimeOut(function(){
       console.log('Time done');
    },3000);
}

waitForThreeSeconds();
console.log('finished execution');

在上面的代码中,当调用 waitForThreeSeconds 函数时,会在 setTimeout 方法的事件队列中放置一个事件。我的问题是,当调用waitForThreeSeconds函数时,JS引擎遇到setTimeout方法时,传入setTimeout的函数表达式中的三秒定时器是否会立即启动?或者将一个事件放置在事件队列中。然后console.log("finished execution')这行代码在全局执行上下文中运行(这意味着一切都在JS文件中执行完毕)之后,三秒定时器将启动,并且传递给setTimeout的回调函数将运行.

我不确定 setTimeout 函数中的计时器何时真正启动。是在JS引擎遇到setTimeout方法时准确启动,还是在JS引擎进入事件队列处理setTimeout方法放置的事件时启动三秒定时器?

【问题讨论】:

标签: javascript timer


【解决方案1】:

所以我们应该已经知道,JavaScript 不是多线程语言,因此是单线程语言,尽管您可以添加事件、终止事件,甚至调用事件。

创建事件时,您将事件标记添加到队列顶部,因此它将是最后一个被识别的事件。

在您的代码中,会发生以下情况:

waitForThreeSeconds():
通话等待三秒

致电setTimeout([...], 3000):
将事件添加为事件队列中的最后一个标记

此时您的事件队列应如下所示:
[this.event, that.event, all.otherEvents, ECMA.TimeStamp(3000)]

TimeStamp(3000) 是我们表示计时器的方式...

因此,JS 引擎每 1/1000 秒(抽象地)就会检查事件队列中是否有已调用的事件。当它识别出TimeStamp(3000) 已被调用时(3000 毫秒后),它现在将调用回调函数。

奇怪的是,当你说setTimeout([...], 3000) 时,JS 引擎会将回调添加到事件队列中,然后从那里继续。它不会等待 3 秒后继续执行下一行代码。

所以只要你打电话给setTimeout(),它就会启动计时器。因此,如果运行其余代码需要 2000 毫秒,那么 1000 毫秒后您的回调将被调用... =)

如果您有任何问题,请发表评论!

【讨论】:

  • JS 引擎不太可能每毫秒轮询一次队列以获取计时器事件,因为这在 CPU 使用率和电池寿命方面都非常低效。每个操作系统都支持计时器事件或计时器通知,在实际计时器触发之前,它们不需要 CPU 也几乎不需要电池。这就是 Javascript 执行计时器事件的方式。它使用操作系统服务作为计时器。
  • 回答 Clay Horder 的问题:即使程序的其余部分运行需要 4000ms,那么在 3000ms 内仍然会调用回调,也就是说会调用回调,然后 1000ms 后程序会跑完
  • 而对于jfriend00的回应,你是完全正确的,但是尽管JS使用系统工具有时间,它仍然需要经常检查这些信息。所以 JS 会回到事件队列,请求系统的日期和时间,看是否应该发起回调。现在虽然每 1 毫秒检查一次事件效率低下,但这只是作为示例,而不是作为实际表示。
  • 回答你的第一个问题:请记住,尽管 JavaScript 有严格的规定,不能在函数中间停下来做其他事情……setTimeout() 是一个原始函数,所以它会直接通信与浏览器...允许浏览器和引擎违反某些规则
  • 第二个问题:如果你打开你的控制台,再看一遍,在console.log()消息的右边,你会看到一个红色的圆圈,里面有一个数字。 . 浏览器这样做,因为如果一个网页多次使用Console.log()log 同一条消息,它可能是垃圾邮件,所以它不会多次记录同一条消息,而是在里面放一个带有数字的红色气泡, 表示它已被多次调用!
【解决方案2】:

setTimeout被添加到“任务队列”末尾的任务中:

function waitForThreeSeconds(){
setTimeout(function(){
   console.log('Time done');
},0);} waitForThreeSeconds();console.log('finished execution');

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-24
    相关资源
    最近更新 更多