4-1:JS 如何基于 EventLoop 实现所谓的“异步”效果
在 Javascript 中本质上是基于栈的形式去执行我们的代码,但是执行任务是如何被推到栈中的呢?
这里我们就不得不提出事件队列的概念,所谓事件队列(Event Queue)正是负责将即将执行的函数发送到栈中进行处理,它队列数据结构保证所有发送执行的正确顺序。
栈中如果执行完毕时。此时 JavaScript 会继续进入事件队列(Event Queue)中查找是否存在需要执行的任务,如果存在那么会继续执行这个队列中的任务。(需要注意的是事件队列中的执行顺序是基于队列先进先出的顺序)。
它仍然需要等待队列前的所有排队任务被执行完毕之后才会被执行。
我们以浏览器中的 SetTimeout 为例来举一个简单的例子来帮助你理解这一过程:
function fn() {
const a = 'test'
console.log(a)
setTimeout(() => {
console.log('hello')
}, 0)
console.log(a+1)
}
fn()
1、fn() 被推入栈中。此时 JS 会在栈中调用这个函数,fn 首先会依次执行一行一行代码。
2、当在栈(fn)中处理 setTimeout 操作时,它会被发送到相应的定时器线程去处理,定时器线程等待指定时间满足后将该操作发送回事件队列。
需要注意的是时间满足后,定时器线程会将需要执行的 callback 函数发送到事件队列中,此时事件循环会检查当前栈中是否存在正在执行的函数。如果为空,则从事件队列中添加新函数推入栈中进行执行。如果不是,则继续处理当前栈中的函数调用。
Javascript 本身是单线程的,但我们可以借助浏览器相关的其他线程以及事件队列的机制来实现异步。
因此,我们基于这样的事件循环模型就实现了达到了所谓的“异步”效果