【问题标题】:how nested setTimeout method gets executed in sequence?嵌套的 setTimeout 方法如何按顺序执行?
【发布时间】:2021-08-01 12:32:45
【问题描述】:
    setTimeout(() => {
        console.log(1);
        setTimeout(() => {
            console.log(2);
            setTimeout(() => {
                console.log(3);
            }, 1000);
        }, 1000);
    }, 1000)

为什么这段代码允许您按顺序每隔一秒控制台登录一次?我预计代码会同时运行 1、2、3,因为所有计时器都设置为 1000 毫秒。

【问题讨论】:

  • “等待一秒钟打印 1,然后等待一秒钟打印 2”应该会在两秒钟内发生。
  • 这能回答你的问题吗? setTimeout or setInterval?
  • 嗯,它们是嵌套的。第二次超时在console.log(1) 运行的同时安排。它比调度时间提前 1000 毫秒被调度,而不是某个固定的初始时间点。
  • 您是否也尝试过不嵌套运行代码?那会是你描述的结果。
  • @Kinta 代码逐行执行,但函数内部的代码在调用函数之前不会执行。

标签: javascript asynchronous callback settimeout nest


【解决方案1】:

传递给setTimeout 的延迟参数是最少时间量回调函数被执行之前;这不是回调运行的实际时间。

回调按照其计时器到期的顺序运行并被推入任务队列。当堆栈为空时,它们会从任务队列中被推入调用堆栈。

在任务队列中最先推送的回调是第一个被推送到调用堆栈的回调。因此它是第一个被执行的。

为什么此代码允许您按顺序每隔一秒控制台登录一次?

这是因为每个内部setTimeout 回调还需要考虑包装器setTimeout 的延迟。

第二个setTimeout的回调函数有2秒的延迟,因为第二个setTimeout被调用第一个定时器在1秒后到期。

同样,最里面的setTimeout有3秒的延迟。

【讨论】:

  • 有什么理由为什么在第一个计时器在 1 秒后到期而不是等待它到期后调用第二个 setTimeout?我用调试器检查了代码,正如你所说,第二个和第三个 setTimeout 从未被执行,甚至在前一个 setTimeout 完成之前读取它的计时器。
  • @Kinta 是的,有。因为第一次超时必须触发才能安排下一次超时。如果我给你一个盒子,上面写着“1分钟后打开”,你需要等待一分钟才能打开它。当你打开它时,如果你看到另一个没有“1分钟后打开”的盒子,你需要再等一分钟才能打开它。这就是执行的工作原理——每个函数都是一个盒子。在运行函数之前,您不会处理内部。
  • @Kinta VLAZ 在上面的评论中提出的类比应该可以帮助您理解代码中发生了什么。由于第二个setTimeout内部 调用第一个setTimeout 的回调函数,因此第二个setTimeout 仅在第一个setTimeout 的回调函数执行时才被调用并且大约发生在 1秒之后。您不能期望第一个setTimeout 的回调函数中的任何代码在实际调用回调之前执行
【解决方案2】:

您在第一个计时器的主体内设置了第二个计时器,所以 1000 毫秒后已经过去了。 因此它比第一个计时器晚一秒运行。你的第三个计时器也是如此。

如果您希望它们同时运行,您需要同时调用setTimeout并且“同一时间”与“考虑到计时器的工作方式尽可能接近”。如果您真的想一次按顺序运行它们,请使用单个setTimeout

【讨论】:

    猜你喜欢
    • 2020-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多