分享我对js事件循环的小小理解

59 阅读3分钟

js事件循环(event loop)

认识进程和线程

  • 进程(工厂):正在进行的程序,是操作系统独立运行的一个个体,系统需要给其分配资源(cpu、内存)。

  • 线程(车间):是操作系统独立运行任务的最小单位。

执行多任务的时候,cpu会在多个线程间做着快速的切换。

  • 电脑是多进程的。可以运行多个程序
  • 浏览器是多线程的,意味可以同时运行多个任务。
  • 浏览器包含的线程:
    1. UI渲染线程:负责解析html和css,绘制页面
    2. js引擎(单线程): 负责解析js代码
    3. 事件线程:单击事件onclick
    4. 网络线程: 网络请求-ajax
    5. 时间器线程: 定时器(setTimeIntval)和延时器(setTimeout)
    6. ....

以上除了js引擎线程,其他线程都是web浏览器提供的Api,统称为webApi。

注意:UI渲染线程和js引擎线程是互斥的,即不能同时运行

js为什么要成设计单线程的?

主要与js功能有关。最开始js是运行在浏览器端的。如果设计成多线程的话,一个线程增加DOM节点,另一个线程删除DOM节点,这样就容易造成冲突。

JS引擎是单线程

  • 只有一个调用栈(call stack)
  • 同一时刻只能做一件事。前面的事没做完,后面就要等着。

但调用栈中遇到了一些耗时的任务如时间器网络请求等操作,浏览器会启用相应的线程去处理它

这些耗时的任务我们称之为异步任务

注意:时间器设置的时间只是理论上中最短的等待时间。

任务队列

  • 所有异步任务的回调(cb),最终都会放入到任务队列中等待执行。
  • 队列特点:先进先出,后进后出。 即先进来的任务先执行,后进来的任务后执行。

队列分类:

  • 宏任务队列。如 script(整个代码区) ajax、fetch、setTimeout ...
  • 微任务队列。如 then、...

若程序中有同步任务和异步任务,执行顺序为:

先同后异,先微后宏。 即先执行完所有的同步代码,剩下的异步代码按照先微后宏的顺序执行。

事件循环过程

script代码区就是一个最大的宏任务。

执行宏任务,然后执行该宏任务产生的微任务,若微任务在执行过程中产生了新的微任务,则继续执行微任务,微任务执行完毕后,再回到宏任务中进行下一轮循环。

事件循环.png

理解事件循环

由于因为js引擎是单线程的,即只有一个调用栈,即同一时刻只能干一件事件。

如调用栈中遇到了比较耗时的任务,会由浏览器开启其他线程去处理这个耗时的任务,最后把这些异步任务的回调放入到任务队列中,等待排队执行。

调用栈中的任务执行完毕之后,会从任务队列中取出下一个任务放在调用栈中执行,执行完后再取出下一个任务执行,循环往复此过程,这就是事件循环。