事件机制(Event Loop)

83 阅读3分钟

太复杂了,其实理解起来很容易,宏任务队列和微任务队列,系统首先开始执行主线,遇到宏任务,加入到宏任务队列,遇到微任务也加入微任务队列,然后主线往下执行,直到主线执行完毕,系统会查看微任务队列中是否存在微任务,如果存在,则将所有微任务也按主线方式执行完成,然后清空微任务,开始将宏任务队列中的第一个宏任务设置为主线继续执行,直到所有的宏任务队列执行清空完成。

所谓Event Loop,就是事件循环,其实就是JS管理事件执行的一个流程

www.ruanyifeng.com/blog/2014/1…

juejin.cn/post/684490…

JS异步的实现靠的就是浏览器的多线程

JavaScript是单线程的,也就是说同一时间只能干一件事。

这是因为JavaScript主要是用来操作DOM的,如果变成多线程,浏览器就懵逼了,不知道该听谁的了。但是虽然js是单线程,但是完全可以模拟多线程,靠的就是Event Loop。

同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

  1. 所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
  2. 主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
  3. 一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
  4. 主线程不断重复上面的第三步。

只要主线程空了,就会去读取"任务队列",这就是JavaScript的运行机制。这个过程会不断重复,所以整个的这种运行机制又称为Event Loop(事件循环)。

同步代码----执行栈

异步代码----队列

我们的 同步 代码就放在 执行栈 中,那异步代码呢?浏览器会将 dom事件 ajax setTimeout等异步代码放到队列中,等待执行栈中的代码都执行完毕,才会执行队列中的代码,是不是有点像发布订阅模式。

异步任务 分为 微任务(microtask) 和 宏任务(task),执行的顺序是 执行栈中的代码 => 微任务 => 宏任务。

执行栈

  • 执行栈中的代码永远最先执行

微任务(microtask): promise MutationObserver...

  • 当执行栈中的代码执行完毕,会在执行宏任务队列之前先看看微任务队列中有没有任务,如果有会先将微任务队列中的任务清空才会去执行宏任务队列

宏任务(task): setTimeout setInterval setImmediate(IE专用) messageChannel...

  • 等待执行栈和微任务队列都执行完毕才会执行,并且在执行完每一个宏任务之后,会去看看微任务队列有没有新添加的任务,如果有,会先将微任务队列中的任务清空,才会继续执行下一个宏任务

juejin.cn/post/717100… 这里有很好的例子

setTimeout和setIntervel执行顺序:相同的时间,谁在前谁先执行。

image.png