浏览器的进程和线程
一、js的单线程和异步
- js的单线程(single threaded)和异步(asynchronous)两个基本矛盾的概念是怎么整合到js上的
- 首先必须肯定js本身不可能是异步的,但js的宿主环境(比如浏览器,Node)是多线程的
- 宿主环境通过某种方式(事件驱动)使得js具备了异步的属性
二、浏览器的进程
- 浏览器的主进程:负责协调、主控
- 第三方插件进程:每种类型的插件对应一个进程,仅当使用该插件时才创建
- GPU进程:最多一个,用于3D绘制等
- 浏览器渲染进程(浏览器内核):主要作用为页面渲染,脚本执行,事件处理等
三、浏览器内核线程
1、JS引擎线程
- JS引擎一直等待着任务队列中任务的到来,然后加以处理
- 一个Tab页中无论什么时候都只有一个JS引擎在运行JS程序
2、GUI渲染线程
- GUI渲染线程与JS引擎线程是互斥的
- 当JS引擎执行时GUI线程会被挂起
- GUI更新会被保存在一个队列中等到JS引擎空闲时执行
3、定时器线程
- 传说中的setInterval与setTimeout所在线程
- 二者的定时计数功能不是由JS引擎完成的,而是通过单独的线程来完成的,从而保证计时准确
- 计时完毕,将回调添加到事件队列中,等待JS引擎空闲执行
4、事件触发线程
- 点击事件等会在对应条件触发的时候被添加到事件队列,等js引擎空闲执行
- 说白了就是内核通过一个单独的线程来进行事件的监听和处理
5、异步HTTP请求线程
- 在发送http请求的时候,这个线程会被执行
- 这个线程会把回调的事件放入到事件队列中等待js引擎执行
总结:浏览器多进程,浏览器内核多线程
事件循环(JS执行机制)
一、同步和异步任务
- javascript是一门单线程语言,所有任务需要排队,前一个任务结束,才会执行后一个任务
- 如果上一个任务的执行过程耗时很长,下一个任务就不得不等待很长的时间,所以任务分成了 同步任务 和 异步任务
- 同步任务在主线程上是一个个执行,而异步任务则会进入任务队列(task queue),只有在所有同步任务执行完,异步任务才会被执行
1、同步异步任务的执行机制
- js中的异步的代码主要是定时器、事件响应回调、异步请求(ajax)
- 上面的三者都会在 Event Table 中注册回调函数,适当的时候(定时到时、事件触发、请求完成)会将这些函数推入到Event Queue,等待js引擎的执行
2、setTimeout & setInterval
- 二者并不能保证到了相应的时间后会立即执行
- 比如下面的这段代码并不是 3 秒之后就能输出setTimeout里面的内容,遇到setTimeout,会将里面的任务注册到 Event Table,这里的定时3秒,意思是3秒之后会将这个任务推入到 Event Queue 等待js引擎的执行,但是js引擎空闲的时候才能执行它呀,要是一直有一个比较耗时的任务一直霸占着js引擎的话,就不能保证这个定时任务到底什么时候执行了
- setInterval 也是一样的,这就导致了一旦setInterval的回调函数执行时间超过了延迟时间ms,那么就完全看不出来有时间间隔了
function sleep(delay) {
var start = (new Date()).getTime();
while ((new Date()).getTime() - start < delay) {
continue;
}
}
setTimeout(() => {
console.log('test-----');
},3000)
sleep(10000)
二、宏任务和微任务
- 看到有的文章里面说宏任务和微任务是异步任务的两种,感觉不是很准确,个人觉得同步异步任务和宏微任务仅仅是从两个不同的维度对js的任务进行划分而已
1、常见的宏任务和微任务
- macro-task(宏任务):包括整体代码script,setTimeout,setInterval
- micro-task(微任务):Promise,process.nextTick(Node里面的内容)
2、js事件循环的简单描述
- 宏任务和微任务在js 的执行过程中相应的二者分别进入宏任务和微任务队列
- 一次完整事件循环过程:宏任务-----清空微任务队列(全部执行)----UI渲染-----再取一个宏任务执行(开始下一次循环)
注意点
- 宏任务是一次取一个进行执行,首次执行代码可以看成是一次宏任务
- 微任务的执行时机是宏任务执行结束后到UI渲染的间隙
- 一次循环的过程,微任务队列会被清空,也就是全部执行完
三、一个示例展示事件循环的过程
- 第一次循环的输出是:1、7、6、8
- 第二次循环的输出是:2、4、3、5
- 第三次循环的输出是:9、11、10、12
console.log('1');
setTimeout(function() {
console.log('2');
process.nextTick(function() {
console.log('3');
})
new Promise(function(resolve) {
console.log('4');
resolve();
}).then(function() {
console.log('5')
})
})
process.nextTick(function() {
console.log('6');
})
new Promise(function(resolve) {
console.log('7');
resolve();
}).then(function() {
console.log('8')
})
setTimeout(function() {
console.log('9');
process.nextTick(function() {
console.log('10');
})
new Promise(function(resolve) {
console.log('11');
resolve();
}).then(function() {
console.log('12')
})
})
参考文章:
https://www.cnblogs.com/hhmm/p/10340542.html
https://blog.csdn.net/lay136362687/article/details/81198076
https://juejin.im/post/59e85eebf265da430d571f89
来源:CSDN
作者:stanwuc
链接:https://blog.csdn.net/stanwuc/article/details/103973633