进程和线程
浏览器打开一个页面就相当于开一个“进程”(程序),在程序中,我们会同时做很多事情,每一个事情都有一个“线程”去处理,所以一个进程中可能会包含多个线程!!
浏览器是多线程的:
- GUI渲染线程:渲染页面 & 绘制图形
- JS引擎线程:渲染和解析JS代码
- 事件触发线程:监听事件触发
- 定时触发器线程:给定时器计时的
- 异步HTTP请求线程:基于HTTP网络从服务器端获取资源和信息
- WebWorker
同时做多件事情是“异步编程”;一次只能处理一件事,上一件事情处理完,下一件才能开始处理,这种操作是“同步编程”;
异步编程实现机制:
- 多线程机制
+ EventLoop事件循环机制JS是单线程的(浏览器只分配一个线程“JS引擎线程”用来渲染和解析JS代码)
- JS中的大部分操作都是“同步”
+ 有少部分操作,结合EventLoop机制,实现了“异步”处理
「异步宏任务:macrotask」
+ 定时器:setTimeout/setInterval
+ 事件绑定/队列
+ 数据请求:Ajax/Fetch
+ MessageChannel
+ setImmediate「NODE」
+ …
「异步微任务:microtask」
+ Promise.then/catch/finally
+ async/awai
+ queueMicrotask
+ MutationObserver
+ IntersectionObserver
+ requestAnimationFrame
+ process.nextTick「NODE」
- JS中的大部分操作都是“同步”
第一如果宏任务之后碰到循环体 无论定时器时间是否到期 都无法执行,因为JS 是单线程的 但在循环的过程中浏览器会把之前的宏任务会依次放到EventQueue中 ,第二 **EventQueue中先执行微任务在执行宏任务**
宏任务(macrotask) | 微任务(microtask) | |
---|---|---|
谁发起的 | 宿主(Node、浏览器) | JS引擎 |
具体事件 | 1. script (可以理解为外层同步代码) 2. setTimeout/setInterval 3. UI rendering/UI事件 4. postMessage,MessageChannel 5. setImmediate,I/O(Node.js) |
1. Promise 2. MutaionObserver 3. Object.observe(已废弃; Proxy 对象替代)4. process.nextTick(Node.js) |
谁先运行 | 后运行 | 先运行 |
会触发新一轮Tick吗 | 会 | 不会 |
setTimeout(() => {
console.log(1);
}, 20);
console.log(2);
setTimeout(() => {
console.log(3);
}, 10);
console.log(4);
console.time('AA');
for (let i = 0; i < 90000000; i++) {
// do soming
}
console.timeEnd('AA'); //=>AA: 79ms 左右
console.log(5);
setTimeout(() => {
console.log(6);
}, 8);
console.log(7);
setTimeout(() => {
console.log(8);
}, 15);
console.log(9);