JavaScript中的事件循环
本文最后更新于:几秒前
线程与进程
- 进程(process)
保存在硬盘中的程序会被载入到内存中运行,在内存空间里面形成一个独立的内存体,这个内存体由自己独立的地址空间、系统也会为应用的每一个进程分配独立的CPU、内存等资源
-
线程(thread)
进程中执行的每一个任务指的就是线程,系统不会为其分配内存资源,各个线程共享进程拥有的内存资源
进程是CPU资源分配的最小单位
线程是CPU调度的最小单位
事件循环是什么
JavaScript 是一门单线程的语言,意味着同一时间内只能做一件事,但是这并不意味着单线程就是阻塞,而实现单线程非阻塞的方法就是事件循环
在JS中,所有的任务都可以分为
-
同步任务:立即执行的任务,同步任务一般会直接进入到主线程中进行
-
异步任务:异步执行的任务,比如ajax请求,定时器等
同步任务和异步任务的运行流程图如下:
同步任务进入主线程,即主执行栈,异步任务进入任务队列,主线程内任务执行完毕后,去任务队列读取对应的任务并且推入主线程执行,上述过程的重复就是事件循环
-
首先判断js代码是同步还是异步,同步就进入主线程,异步就进入event table
-
异步任务在event table中注册函数,当满足触发条件后,被推入event queue
-
同步任务进入主线程后一直执行,直到主线程空闲时,才回去event quene中查看是否有可执行的异步任务,如果有就推入主线程中
-
event table(回调函数对应表):用来存储JS中的异步事件(request, setTimeout,IO等)及其对应的回调函数列表
宏任务和微任务
为什么引入微任务?
异步任务也有优先级之分,例如DOM操作如果等待过久给用户的体验不好
所以JS的执行机制是:
-
执行一个宏任务,如果遇到微任务就把它放到微任务的事件队列中
-
当前宏任务执行完成后,会查看微任务的事件队列,然后将里面的所有微任务依次执行完
常见的宏任务
-
script
-
setTimeout
-
setInterval
-
UI rendering
-
I/O (node.js)
-
setImmediate (node.js)
常见的微任务
-
Promise.then
-
MutaionObserver
-
process.nextTick(node.js)
async 和 await
async
是异步的意思,await
则可以理解为 async await
。所以可以理解为async
就是用来声明一个异步方法,而await
是用来等待异步方法执行
async
async
函数返回一个promise
对象,下面两种方法是等效的
1 |
|
和
1 |
|
await
正常情况下,await
命令后面是一个Promise
对象,返回该对象的结果,如果不是Promise
对象,就直接返回对应的值
1 |
|
不管await
后面跟着什么,await
都会阻塞后面的代码(即加入微任务队列)