JS异步(二)| 异步是怎么回事、eventloop

date
May 22, 2021
slug
JavaScript-eventloop-and-async
status
Published
tags
JavaScript
type
Post
summary
异步是怎么回事、eventloop
js是单线程的,无论在什么运行环境。虽然浏览器里可以有一个web worker多线程,但是还是有些问题,基本数都是单线程,那我们可能有些奇怪,JS不是单线程嘛,怎么还能创建HTTP?
答案就是----------异步

1 原理

为什么定时器设置1秒,实际上是3秒后执行呢?
因为后面的for循环,循环没执行完,console.log也没执行
那问题来了!为什么JS是单线程还能实现定时器呢? 如果是单线程,执行到定时器就应该Blocking了,1秒后才会执行循环。 答案很简单,因为浏览器是多线程的。浏览器是多线程的和JS是单线程的一点也不矛盾。这里用到一个技术叫做event loop也叫做事件轮询模型,node里面叫做非阻塞IO,实际上就是一个东西。
这玩意就是异步的原理
简单来说,定时器是一个耗时的操作,所以有两种情况,
  • 一种是等1000ms,这1000ms CPU空转,
  • 还有一个是创建一个线程,等待1000ms执行后面的代码,其余代码在主线程执行。
    • 这不止针对JS
但是第二种也有缺陷
  • 一个定时器就创建一个线程,资源占用严重
  • 等定时器执行完,回到主线程是,如果主线程有任务,那么线程之间很有可能进入竞争态。最后的结果就不知道是啥了
所以JS用了第三中方法!异步

2 异步的实现

  • 首先JS里面有个任务队列,JS的引擎/虚拟机/VM会执行JS脚本,当JS空闲的时候,会去这个任务队列里面取找任务执行,,任务队列是在内存的一块区域,JS的线程也就是浏览器的主线程会访问它。(如果运行在node里就是node去访问,这个是根据运行环境决定的。)
  • 浏览器是多线程的,大概有事件线程,XHR线程,定时器线程等等
    • 一个demo
      这段代码是这样执行的
    • 首先执行完 var a
    • 下面注册了个定时器
    • 这里要等1000ms,浏览器主线程认为这个太耗时间了,他不会自己等,他会委托给浏览器的其他魔火,比如定时器模块,让定时器模块去处理,然后主线程继续下面的循环,循环可能直线到一般的时候。比如循环到500次的时候。1秒到了
    • 浏览器的定时器模块推送了一个任务放在主线程的任务队列里
    • 这时候,马上会执行定时器的callback嘛?答案是不会,浏览器要先把手头的活干完,然后100000次循环都整好了以后,这时候主线程会闲的没事干,没事干就会给自己找事干,然后他去遍历任务队列,一看,好家伙,这有个任务,然后就拿出来执行,这样循环往复,这就叫做event loop,而任务队列里的任务就叫做异步任务。
  • 几个问题
    • event loop 任务队列,是谁推送的-----运行环境
    • 刚刚那个demo是setTimeout的时候推送任务的还是1秒后推送任务的------1秒后(这个等待的事就交给浏览器的定时模块了)
  • 图解
    • notion image
      notion image

3 例子

    notion image
      由此可见所有的异步代码必然在同步代码之后才执行

      © dana 2023 - 2025