js是单线程的,那么是否代表参与js执行过程的线程只有一个?
答案:不是的,一共有4个线程参与该过程,但是永远只有js引擎线程在执行js脚本程序,其它3个线程都是在辅助,不参与代码的解析与执行。
4个线程分别是:
js引擎线程:也称为js内核,负责解析执行,是负责javascript脚本程序的主线程。(例如v8引擎)
事件触发线程:归属于浏览器内核进程,不受js线程控制,主要用于控制事件(例如键盘、鼠标事件),当该事件被触发时,事件触发线程就会把该事件的处理函数推进事件队列,等待js引擎线程执行。
定时器触发线程:包括settimeout、setinterval,满足触发条件,则将定时器处理函数推进事件队列,等待js引擎线程执行。
HTTP异步请求线程:通过XMLHttpRequest连接后,通过浏览器新开的一个线程,监控readyState状态变更时,如果设置了该状态的回调函数,则将该状态的处理函数推进事件队列中,等待JS引擎线程执行。
整个代码执行过程大概分为:
宏任务:
同步任务:在js引擎线程执行的任务,按顺序执行,只有上一个程序执行完,才可以执行下一个任务,形成一个执行栈。
异步任务:不直接进入js引擎主线程,再满足条件时触发,相关线程将该异步任务推入任务队列,等待js引擎主线程上的任务完毕,空闲时执行任务。例如异步ajax、dom事件、settimeout等。
微任务:
js引擎执行过程:(进入执行阶段后)
宏任务(同步任务)> 微任务 > 宏任务(异步任务)
理解宏任务中同步任务和异步任务的执行顺序,那么就相当于理解了JS异步执行机制–事件循环
事件循环大概由三部分组成:
主线程执行栈、异步任务等待触发、任务队列
主要过程:
首先宏任务的同步任务 js引擎主线程执行,形成一个执行栈,就是函数执行栈。
当执行栈中的函数调用到一些异步API,则会开启对应的线程行进控制和监控。
检查是否有可执行的微任务,有的话会执行所以微任务,读取任务队列的任务事件,推进主线程形成新的宏任务。再检查是否存在可执行的微任务,如此不断的重复循环
当异步任务满足触发条件时,对应线程会把还事件的处理函数推入任务队列,等待主线程读取执行。
当js引擎主线程任务执行完毕,则会读取任务队列中的事件任务,将任务队列的事件推入到主线程当中,按任务队列顺序执行。
当js引擎主线程任务执行完毕后,则会再次读取任务队列中的事件。