原文链接:JavaScript运行机制
1.了解进程与线程的基础概念,明确在浏览器中的进程与线程机制;
2.了解浏览器与Node中的事件循环;
进程:CPU资源分配的最小单位。——可以独立运行且拥有自己的资源空间的任务程序。(包括运行中的程序和程序中所用到的内存和系统资源)。
eg:每打开一个软件就会产生一个进程,浏览器中每开一个Tab页也会产生一个进程。进程之间相互独立。
线程:CPU调度的最小单位。——建立在进程基础上的一次程序运行单位。一个进程可以有多个线程。一个程序中可以同时运行多个不同的线程来执行不同的任务。
进程包含了线程,一个进程可以对应多个线程。线程相当于是进程中的不同执行路线。
调度和切换:线程上下文切换比进程上下文切换要快得多。
JS主要用途是与用户互动,以及操作DOM。
如果JS是多进程的话,那么它可以同时在某个DOM节点上添加内容,又可以删除这个节点,从而导致浏览器不知该以哪个为准。
浏览器包含以下进程:
若浏览器是单进程,那么如果某个Tab页崩溃了,则会导致整个浏览器瘫痪,同理,如果插件崩溃了则会影响整个浏览器,这样体验感非常差。
页面渲染,JS的执行,事件的循环,都在渲染进程中执行,所以需要重点了解渲染进程。
渲染进程是多线程的,以下是一些常用较为主要的线程:
1.解析html代码转化为浏览器认识的节点,生成DOM树,
2.解析CSS,生成CSSOM(CSS规则树)
3.把DOM Tree 和 CSSOM结合,生成Rendering Tree(渲染树)
1.当JS引擎线程执行时,GUI渲染线程会被挂起
2.GUI渲染线程会被保存在一个队列中等到JS引擎空闲时立即被执行
我们可以把每次执行栈中执行的代码当作是一个宏任务(包括从事件队列中取出一个事件回调放到执行栈中执行),每一个宏任务都会从头至尾执行,不会执行其他。宏任务中的代码都是同步的。
由于JS引擎线程和GUI渲染线程互斥,所以浏览器为了宏任务和DOM任务有序的进行,会在每一个宏任务执行完毕后,都会在下一个宏任务执行前,GUI渲染线程开始工作,对页面进行渲染。
常见的宏任务有以下几种:
微任务为在当前宏任务执行后立即执行的任务。
当一个宏任务执行完,会在渲染前,将执行期间所产生的所有微任务都执行完:
*任务执行过程:宏任务->微任务->GUI渲染->宏任务->微任务->GUI渲染->xxx*
以下形式的代码为微任务
new Promise(()=>{}).then()中,前面的new Promise(()=>{})是一个构造函数,这是一个同步任务,后面的.then()才是一个异步微任务:
new Promise((resolve)=> {
console.log(1);
resolve();
}).then(()=> {
console.log(2)
})
cosole.log(3)
// 1 3 2
async/await本质上还是基于Promise的一些封装,而Promise是属于微任务的一种
所以在使用await关键字的效果与Promise.then效果类似,await以前的代码,相当于new Promise的同步代码,await以后的代码,相当于Promise.then的异步
setTimeout(()=> console.log(4)) // 进入下一次事件循环
async function test(){
console.log(1)
await Promise.resolve()
console.log(2)
}
test()
console.log(3)
// 1 3 2 4