前言
时间不知不觉来到了11月底,马上也要准备一下寒假的实习了。 最近打算把面试中的一些拦路虎给解决掉!!
先拿臭名昭著的Eventloop
开刀~
经典题
async function foo() {console.log('foo')
}
async function bar() {console.log('bar start')await foo()console.log('bar end')
}
console.log('script start')
setTimeout(function () {console.log('setTimeout')
}, 0)
bar();
new Promise(function (resolve) {console.log('promise executor')resolve();
}).then(function () {console.log('promise then')
})
console.log('script end')
今天刚准备手刀Eventloop的时候,差点就被这个题劝退了😭😭
但现在我终于能拿捏它了~
😁😁
Eventloop(事件循环):是怎么让页面活起来的
我们都知道主线程是非常繁忙的,既要处理 DOM,又要计算样式,还要处理布局,同时还需要处理 JavaScript 任务以及各种输入事件。要让这么多不同类型的任务在主线程中有条不紊地执行,这就需要一个系统来统筹调度这些任务。
这个统筹调度系统就是消息队列
和事件循环系统
使用单线程处理安排好的任务
我们先从最简单的场景讲起,比如有如下一系列的任务:
任务 1:1+2
任务 2:20/5
任务 3:7*8
任务 4:打印出任务 1、任务 2、任务 3 的运算结果
在上面的执行代码中,我们把所有任务代码按照顺序写进主线程里,等线程执行时,这些任务会按照顺序在线程中依次被执行;等所有任务执行完成之后,线程会自动退出。可以参考下图来直观地理解下其执行过程:
在线程运行过程中处理新任务
但并不是所有的任务都是在执行之前统一安排好的,大部分情况下,新的任务是在线程运行过程中产生的。比如在线程执行过程中,又接收到了一个新的任务要求计算“10+2”,那上面那种方式就无法处理这种情况了。
要想在线程运行过程中,能接收并执行新的任务,就需要采用事件循环机制
处理其他线程发送过来的任务
面我们改进了线程的执行方式,引入了事件循环机制,可以让其在执行过程中接受新的任务。不过在第二版的线程模型中,所有的任务都是来自于线程内部的,如果另外一个线程想让主线程执行一个任务,利用第二版的线程模型是无法做到的。
那么如何设计好一个线程模型,能让其能够接收其他线程发送的消息呢?
一个通用模式是使用消息队列。
有了队列之后,我们就可以继续改造线程模型了,改造方案如下图所示: