繁体   English   中英

为什么 setInterval function 无法阻止 setTimeOut 运行?

[英]Why setInterval function cannot stop setTimeOut from running?

我正在学习 Javscript 并尝试了这段代码:

var a=true;
let c=0;
setTimeout(()=>{
console.log("a is false");
},2000);

setInterval(()=>{
console.log(c++);
},200)

我在想这段代码在执行时会产生一个无限循环,但事实并非如此。

由于 JS 是一种单线程语言,我们让 setInterval 每 200 毫秒运行一次,因此它停留在主线程中。2 秒后 setTimeout 应该执行,但由于 setInterval 在那一刻运行,主线程应该被 setInterval 占用。但仍然setTimeout function 被执行,我无法理解..

单线程并不意味着您只有一个执行上下文。 JS 是事件驱动的,虽然不是多线程的,但有一个协调器(称为事件循环),它确保函数调用在它们应该发生的时候发生。

在您的情况下,setInterval 计划每 200 毫秒运行一次,并且如果已计划(例如您的 setTimeout),则不会阻止任何其他代码运行。

这两段代码在同一个线程中运行,并由事件循环正确调度。

另外:你确实有一个无限循环。 setInterval function 永远不会停止。

考虑一下这是代码:

var a=true&&false;
let c=0+1;
setTimeout(function1,1000);
setInterval(function2, 200);

CallStack是执行JS的栈

回调队列是异步代码准备执行时排队的队列

在调用栈和回调队列之间是非常有名的事件循环 它是一个不断监视队列的东西,如果执行调用栈为空,就将队列顶部的东西传递给栈

时间 代码执行
1毫秒 “var a=true&&false;” 被移动到 CallStack 并立即执行
2毫秒 “令 c=0+1;” 被移动到 CallStack 并立即执行
3毫秒 “设置超时(函数 1,1000);” 被移动到 CallStack 并立即执行; 但是这里,执行是将function1交给WebAPI setTimeout; setTimeout API 此时启动一个2000ms的定时器
4毫秒 “设置间隔(函数 2,200);” 被移动到 CallStack 并立即执行; 但是这里,执行是将function2交给WebAPI setInterval; setInterval API 此时启动一个200ms的定时器
5毫秒 No Code in CallStack and Eventloop 在回调队列中找不到任何东西; 所以,没有什么可执行的
... ...
204毫秒 setInterval 将 function2 添加到回调队列; Event循环在回调队列中找到function2,立即交给callStack执行; 控制台日志(C++); 函数 2 被执行
205毫秒 No Code in CallStack and Eventloop 在回调队列中找不到任何东西; 所以,没有什么可执行的
... ...
404毫秒 setInterval 将 function2 添加到回调队列; Event循环在回调队列中找到function2,立即交给callStack执行; 控制台日志(C++); 函数 2 被执行
405毫秒 No Code in CallStack and Eventloop 在回调队列中找不到任何东西; 所以,没有什么可执行的
... ...
604毫秒 setInterval 将 function2 添加到回调队列; Event循环在回调队列中找到function2,立即交给callStack执行; 控制台日志(C++); 函数 2 被执行
605毫秒 No Code in CallStack and Eventloop 在回调队列中找不到任何东西; 所以,没有什么可执行的
... ...
804毫秒 setInterval 将 function2 添加到回调队列; Event循环在回调队列中找到function2,立即交给callStack执行; 控制台日志(C++); 函数 2 被执行
805毫秒 No Code in CallStack and Eventloop 在回调队列中找不到任何东西; 所以,没有什么可执行的
... ...
1003毫秒 setTimeout 将 function1 添加到回调队列; Event循环在回调队列中找到function1,立即交给callStack执行; console.log("a 为假"); function1 被执行
1004毫秒 setInterval 将 function2 添加到回调队列; Event循环在回调队列中找到function2,立即交给callStack执行; 控制台日志(C++); 函数 2 被执行
1005毫秒 No Code in CallStack and Eventloop 在回调队列中找不到任何东西; 所以,没有什么可执行的
... ...
1204毫秒 setInterval 将 function2 添加到回调队列; Event循环在回调队列中找到function2,立即交给callStack执行; 控制台日志(C++); 函数 2 被执行
1205毫秒 No Code in CallStack and Eventloop 在回调队列中找不到任何东西; 所以,没有什么可执行的
... ...

注意在 1003、1004 和 1005 毫秒处发生的情况。 这就是它的工作原理。 关键是非阻塞 I/0。 在这种情况下,Out I/0 是 webApi setTimeout 和 setInterval

PS - 我在代码行 1 和 2 中添加了表达式,因为理想情况下声明不会占用执行时间。 实际上,表达式执行在现代操作系统中花费的时间远远少于 1 毫秒。 这样做只是为了简化目的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM