JS运行机制复习

Js是单线程语言

原因:作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。避免复杂同步问题。

消息队列

JS任务分类:

  1. 同步任务(synchronous)在主线程上排队执行的任务,前一个执行完毕,执行后一个任务。
  2. 异步任务(asynchronous)不进入主线程,进入任务队列(task queue),当任务队列通知主线程,某异步任务可以执行,该异步任务才会进入主线程执行。
console.log("A");
while(true){ }
console.log("B");
console.log("A");
setTimeout(function(){
console.log("B");
},0);
while(true){}

Event Loop

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

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

JS运行机制复习_第2张图片
image.png

任务队列

  1. setTimeout和setlnterval
  2. DOM事件
  3. ES6中的Promise
  4. Ajax异步请求
for (var i = 0; i < 5; i++) {
setTimeout(function() {  
 console.log(i);  
  }, 1000);
}

浏览器渲染进程

GUI渲染进程
  1. 负责渲染浏览器界面,解析HTML,CSS,构建DOM树和RenderObject树,布局和绘制等。
  2. 当界面需要重绘(Repaint)或由于某种操作引发回流(reflow)时,该线程就会执行。(前端性能优化点)
  3. 注意,GUI渲染线程与JS引擎线程是互斥的,当JS引擎执行时GUI线程会被挂起(相当于被冻结了),GUI更新会被保存在一个队列中等到JS引擎空闲时立即被执行。
JS引擎线程
  1. 也称为JS内核,负责处理Javascript脚本程序。(例如V8引擎)
  2. 由于js是单线程(一个Tab页内中无论什么时候都只有一个JS线程在运行JS程序),依靠任务队列来进行js代码的执行,所以js引擎会一直等待着任务队列中任务的到来,然后加以处理。
  3. 同样注意,GUI渲染线程与JS引擎线程是互斥的,所以如果JS执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞。
事件触发线程
  1. 归属于渲染(浏览器内核)进程,不受JS引擎线程控制。主要用于控制事件(例如鼠标,键盘等事件),当该事件被触发时候,事件触发线程就会把该事件的处理函数添加进任务队列中,等待JS引擎线程空闲后执行
定时触发器线程
  1. setInterval与setTimeout所在线程。
  2. 浏览器的定时器并不是由JavaScript引擎计数的,因为JavaScript引擎是单线程的, 如果处于阻塞线程状态就会影响计时的准确,因此通过单独的线程来计时并触发定时器,计时完毕后,满足定时器的触发条件,则将定时器的处理函数添加进任务队列中,等待JS引擎线程空闲后执行。
  3. W3C在HTML标准中规定,规定要求setTimeout中低于4ms的时间间隔算为4ms。
异步http请求线程
  1. 当XMLHttpRequest连接后,浏览器会新开的一个线程,当监控到readyState状态变更时,如果设置了该状态的回调函数,则将该状态的处理函数推进任务队列中,等待JS引擎线程空闲后执行。
JS运行机制复习_第3张图片
image.png

宏任务(macrotask)与微任务(microtask)

console.log('script start');

setTimeout(function() {
    console.log('setTimeout');
}, 0);

Promise.resolve().then(function() {
    console.log('promise1');
}).then(function() {
    console.log('promise2');
});

console.log('script end');

JS中分为两种任务类型:macrotask和microtask,在ECMAScript中,microtask称为jobs,macrotask可称为task

JS运行机制复习_第4张图片
image.png
  1. macrotask:主代码块,setTimeout,setInterval等(可以看到,事件队列中的每一个事件都是一个macrotask)
  2. microtask:Promise,process.nextTick,mutation
  3. 补充:在node环境下,process.nextTick的优先级高于Promise,也就是可以简单理解为:在宏任务结束后会先执行微任务队列中的nextTickQueue部分,然后才会执行微任务中的Promise部分。

你可能感兴趣的:(JS运行机制复习)