JavaScript中的事件循环

本文最后更新于:几秒前

线程与进程

  • 进程(process)

保存在硬盘中的程序会被载入到内存中运行,在内存空间里面形成一个独立的内存体,这个内存体由自己独立的地址空间、系统也会为应用的每一个进程分配独立的CPU、内存等资源

  • 线程(thread)

进程中执行的每一个任务指的就是线程,系统不会为其分配内存资源,各个线程共享进程拥有的内存资源

进程是CPU资源分配的最小单位

线程是CPU调度的最小单位

事件循环是什么

JavaScript 是一门单线程的语言,意味着同一时间内只能做一件事,但是这并不意味着单线程就是阻塞,而实现单线程非阻塞的方法就是事件循环

在JS中,所有的任务都可以分为

  • 同步任务:立即执行的任务,同步任务一般会直接进入到主线程中进行

  • 异步任务:异步执行的任务,比如ajax请求,定时器等

同步任务和异步任务的运行流程图如下:

同步任务进入主线程,即主执行栈,异步任务进入任务队列,主线程内任务执行完毕后,去任务队列读取对应的任务并且推入主线程执行,上述过程的重复就是事件循环

  1. 首先判断js代码是同步还是异步,同步就进入主线程,异步就进入event table

  2. 异步任务在event table中注册函数,当满足触发条件后,被推入event queue

  3. 同步任务进入主线程后一直执行,直到主线程空闲时,才回去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
2
3
function f(){
return Promise.resolve('TEST');
}

1
2
3
async function asyncF(){
return 'TEST';
}

await

正常情况下,await命令后面是一个Promise对象,返回该对象的结果,如果不是Promise对象,就直接返回对应的值

1
2
3
4
5
async function f(){
return await 123;
//等同于 return 123
}
f().then(v => console.log(v)) //123

不管await后面跟着什么,await都会阻塞后面的代码(即加入微任务队列)


JavaScript中的事件循环
https://blog.seasalt-haiyan.top/2024/04/19/JavaScript中的事件循环/
作者
Xu Haoyang
发布于
2024年4月19日
更新于
2024年4月19日
许可协议