setTimeout是否阻塞

0. 结论

从现象上来看,setTimeout是异步的,但原理并不是多线程,而是任务队列的轮询机制,且受主线程阻塞

1. 先看例子

先看以下两种情况的输出:

例一:

sleep(3000);
console.log("start!");
setTimeout(() => {
  console.log(222);
}, 3000)
setTimeout(() => {
  console.log(444);
}, 5000)
setTimeout(() => {
  console.log(666);
}, 1000)

结果如下

start!   // 3s
666      // 4s
222   	 // 6s
444      // 3+5=8s

例二:

console.log(111)
setTimeout(() => {
    console.log(222);
}, 3000)
console.log(333)
setTimeout(() => {
    console.log(444);
}, 0)
console.log(555)
setTimeout(() => {
    console.log(666);
}, 1000)

结果如下

111 // 立即
333 // 立即
555 // 立即
444 // 0s
666 // 1s
222 // 3s

到这里可以说明一点,setTimeout没有阻塞主线程,而且只有执行到setTimeout函数时计时器才开始倒计时,这其实是由于浏览器采用了任务队列的机制

2. 任务队列

在JavaScript中 所有的任务可以分为两种 一种是同步任务(synchronous)另一种是异步任务(asynchronous)
同步任务指: 在主线程上排队执行的任务 只有前一个任务执行完毕后 才能执行下一个任务
异步任务指: 不进入主线程 而进入 任务队列(task queue)的任务 等主线程的任务全部执行完成后 主线程会通过event loop(事件循环) 去询问任务队列中是否有可以被执行的任务了 如果有可以被执行的任务 这个时候这个任务就会被放进 主线程执行

下面这张图就更详细的解释了主线程和任务队列的关系

img

至此 setTimeout并不是异步的 而是JavaScript在执行的时候 会将setTimeout放入任务队列 等待主线程的执行(不阻塞主线程)全部执行完成后 再通过event loop去询问任务队列中是否有可执行的代码 再继续放入主线程中执行 故产生了异步的假象。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值