【问题标题】:In javascript, why doesn't the below code exit the loop?在javascript中,为什么下面的代码不退出循环?
【发布时间】:2021-06-01 01:07:42
【问题描述】:
let a = true;
setTimeout(() => {a = false}, 1000)
while(a){console.log(a)}

【问题讨论】:

  • 因为在循环结束之前我们不会返回事件循环。
  • 这就是所谓的“忙循环”。该超时没有机会执行,因为您的循环不会产生控制权。

标签: javascript node.js loops settimeout single-threaded


【解决方案1】:

因为 JS 是单线程的,setTimeout 会在线程不忙的时候运行 1000 毫秒。由于这个while循环阻塞了线程,setTimeout的回调没有时间运行,因此a永远保持true

您可以在here找到有关此主题的更多详细信息。

【讨论】:

    【解决方案2】:

    setTimeout 是异步函数,提供的回调只有在 javascript 调用堆栈为空时才会执行。由于我们有“while(true)”条件,它总是会执行一些东西 => 调用堆栈永远不会为空 => setTimeout 回调永远不会被执行。 有关更多信息,请阅读 JavaScript 事件循环 https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop

    【讨论】:

      【解决方案3】:

      让我们一步一步看这个(如果这是在浏览器中执行的):-

      let a = true;
      setTimeout(() => {a = false}, 1000)
      while(a){console.log(a)}
      
      • let a = true; :您将新变量a 初始化为true;

      • setTimeout(() => {a = false}, 1000) :您已告诉浏览器的 setTimeout Web API 执行 回调 (() => {a = false}),其中我们将 a 设置为 @987654328 @ 在最少 1 秒之后。 最小,因为除非 JavaScript 执行堆栈(这是您的所有 JS 代码实际同步执行的地方,否则 回调 不会执行强>) 是空的。这个 1s 之后的 回调 被放置在 事件队列 中,并且只有在 JavaScript执行堆栈为空。

      • while(a){console.log(a)} :这将同步执行并阻塞主线程(执行堆栈所在的位置),因为a 始终为真。我们的主线程被阻塞意味着这个操作的完成成本太高(这是有道理的,因为它是无限的日志记录),所以 JavaScript 执行堆栈 永远不会对任何人免费回调事件队列中可用。这意味着 () => {a = false} 即使在 事件队列 中可用,也永远不会有机会出列 并在我们的 JavaScript 执行堆栈中运行。

      浏览器的 Web API、这个 JavaScript 执行堆栈事件队列 共同构成了我们的 事件循环浏览器。

      JavaScript单线程(还记得主线程吗?)同步语言。您在 Web 应用程序或服务器中看到的所有异步行为都是由构成事件循环的其他部分造成的。

      这也是它的简化图。事件队列有更多的划分,但这超出了这个问题的范围。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-11-21
        • 1970-01-01
        • 2020-12-17
        • 2022-12-04
        • 2015-12-06
        • 2016-09-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多