进程和线程
进程:指程序运行专属的内存空间
线程:指每一个进程中的线程(至少一个主线程)
浏览器属于多进程,每一个网页代表着创建一个独立的进程,包含渲染主线程(GUI线程):渲染浏览器界面(即HTML、CSS、JS代码解析)
事件循环
JS单线程运行,异步基于回调来实现,事件循环其实是异步回调的实现原理
从前往后一行一行执行,某一行报错停止执行之后的代码,先执行同步再继续执行异步
如图示:
- Call Stack:调用栈
- Web APIs:浏览器之外定义的相关API(如定时器,事件监听)
- Event Loop:事件轮询
- Callback Queue:回调函数队列(消息队列)
示例:
console.log('hello')
setTimeout(function call(){
console.log('你好')
},3000)
console.log('Bye')
// code...
- 首先会将
console.log('hello')推入调用栈中并执行,完成打印hello,并清空调用栈; - 将
setTimeout推入调用栈执行,在web api中生成定时器并标记call回调,setTimeout执行完毕并清空调用栈,待定时器时间完成后将回调call函数推入Callback Queue(消息队列)中等待执行; - 执行
console.log('Bye')以及所有的同步代码 - 当同步代码全部执行完毕(调用栈为空),将启动Event Loop机制(轮询查找),询问Callback Queue是否有任务,并将任务(函数
call)推送到调用栈执行
同步代码一行一行在调用栈中执行(死循环导致阻塞),遇到异步任务会先进行记录,等待时机(定时,网络请求,事件监听),时机成熟移动到Callback Queue中,当调用栈为空Event loop开始工作,轮询查找Callback Queue,将查找的任务推送到调用栈中执行,然后继续轮询。
消息队列
宏任务: 定时器,ajax,DOM事件
微任务: Promise async / await (微任务优先级高于宏任务)
- 每次调用栈清空(Event Loop每一次轮询结束),即同步任务执行完毕;
- 浏览器都会尝试进行DOM渲染,然后再触发Event Loop。
- WebAPI:DOM( 文档对象模型 )、 BOM、事件绑定、ajax、存储
宏任务: DOM 渲染后触发
- 调用栈(Call Stack清空)
- 执行当前微任务:Promise是ES规范并非W3C规范,不会经过Web APIs会直接进入micro task queue
- 尝试 DOM渲染
- 触发 Event Loop
微任务:DOM渲染前触发
- 调用栈(Call Stack清空)
- 尝试DOM渲染
- 触发Event Loop