目录
前言
JS是单线程语言,在某个时间段只能执行一段代码。这种单线程模型的好处是不会出现多线程的竞态条件和死锁等问题:在多线程中,某个资源同时被其他线程调度时可能会出现执行顺序不确定导致错误,或者资源占用等待这一类的问题。因此JS无法同时处理多任务,为了处理这类任务,JavaScript运行时使用了一种叫事件循环机制的异步编程模型
JS的事件循环机制是一种异步编程模型,其特点是异步非堵塞,它决定了JavaScript的异步执行顺序和运行机制。
JS的事件循环机制由调用栈(Call Stack)、任务队列(Task Queue)、事件循环(Event Loop)组成,它们共同协作实现了JavaScript的异步编程模型,下面我会具体介绍这三个部分以及相关知识
同步/异步编程模型
首先我们熟悉一下同步和异步编程的概念
同步
同步编程模型是一种线性的编程模型,程序必须按照代码的顺序一个接一个地执行任务,直到当前任务执行完毕后,才能执行下一个任务
许多语言有sleep()函数,用于延迟或定时操作,sleep会阻塞当前线程或进程,直到暂停时间结束后才会继续执行下一条语句,这就是同步编程的特点
同步编程模型的优点是简单、直观,易于调试,缺点是程序执行效率比较低,容易阻塞程序的运行
异步
异步编程模型是一种非线性的编程模型,异步模型中任务的执行是非阻塞的,程序不必等待当前任务完成,而是可以继续执行下一个任务,同时等待当前任务的结果
在JS中我们可以同时执行多个异步函数,通过回调,事件,Promise等方式来捕获异步结果,此外,许多语言还引入了async/await的概念用于异步操作
异步编程模型的优点是可以提高程序的执行效率和吞吐量,缺点是比同步复杂,需要处理回调、事件、异常等问题。
JS异步模型
上面我们说到调用栈、任务队列、事件循环共同组成了JS的异步模型,那么我们就来看看其三者之间的关系及工作原理
调用栈
调用栈的作用是存储函数调用的上下文信息,其信息包括函数的参数、局部变量、返回地址等;调用栈是先进后出的结构,每当程序执行一个函数时,该函数会被压入调用栈的顶部,执行结束后会从调用栈中弹出
我们使用可视化工具模拟调用栈的操作
function a() {
console.log('a');
}
function b() {
console.log('b');
a();
}
function c() {
console.log('c');
b();
}
c();

可以看到,函数在执行时会先压入栈,等完全执行完毕后就会被销毁
任务队列
队列的数据结构与上面的栈不同,采用的是先进先出(FIFO)的数据结构,JS的任务队列包含宏任务队列与微任务队列。之前写过一篇关于任务队列的文章,介绍了一下队列的特点:先进入的数据会被优先处理,后进入的数据则会被推迟处理,直到前面的数据处理完毕
JS有两种任务队列,分别是宏任务队列(Macro Task Que

文章详细介绍了JavaScript的事件循环机制,包括同步和异步编程模型的概念,JS异步模型中的调用栈、任务队列(宏任务和微任务队列)以及事件循环的工作原理。通过实例展示了任务队列的优先级,即微任务先于宏任务执行,并提供了事件循环的简单实现。
最低0.47元/天 解锁文章
363

被折叠的 条评论
为什么被折叠?



