前言
事件循环大家都是耳熟能详的,今天我们就来回顾下,我们都知道事件循环的根本原因是在于js是一个单线程语言。
在以往的面试中也许会碰到这样的面试题:
面试官:什么是双线程和单线程,js为什么是单线程的
一般来说,只有进程才会出现线程,一个进程至少是要包含一个线程的。单线程就是只有一个线程,而多线程是包含两个及以上的线程。
我们的js就是在运行时就是一个进程,同时他也是一个单线程,后台语言一般都是多线程的。
浏览器中一般是存在如下线程的:
1·JS引擎线程
作用:负责处理执行javascript脚本
2.UI渲染线程
作用:负责渲染浏览器界面,包括解析HTML、CSS、构建DOM树,render树,绘制等。
3.事件监听线程
作用:用来完成事件处理的,例如:click,mouseover…
4.计时器线程
作用:负责处理定时器。setInterval和setTimeout
5.网络线程
作用:负责处理http网络请求的
js设计成单线程的理由:
js主要是实现用户与浏览器的交互,以及操作dom;这决定了它只能是单线程,否则会带来很复杂的同步问题。 举个例子:如果js被设计了多线程,如果有一个线程要修改一个dom元素,另一个线程要删除这个dom元素,此时浏览器就会卡死,我他妈的到底是要干什么呢,,但是单线程就可以解决这个问题了,我只要通过事件循环就可以解决了,你不是修改吗,第一次改完了,那该轮到我删除了,咱俩轮换着来就行了。
js中的宏任务与微任务
js代码的执行也讲究个先来后到,举个例子,医院的缴费窗口,他就只有一个窗口,外面排起长队,到你了你就缴费就行了,有些人不行,他来到窗口墨迹半天,他说忘拿社保卡了没法看病优惠,没办法,那你就重新往后排队去吧
说白了js就是一个执行队列,队列中有人按照顺序有序进行,有人来回的在队列中排队,等待着去执行。
js中有两种任务队列:第一种是同步任务,第二种就是异步任务。
举个例子:
console.log("小小的花园里啊,挖呀挖呀挖");
setTimeout(()=>{
console.log('美女荷官,在线发牌')
},1000)
Promise.resolve().then(()=>{
console.log('一个人有两颗心,一个是贪心,一个是不甘心')
})
console.log("小小的花园里啊,挖呀挖呀挖"); -----------这就是同步任务
setTimeout(()=>{console.log('美女荷官,在线发牌')},1000)-----异步任务
Promise.resolve().then(()=>{ console.log('一个人有两颗心,一个是贪心,一个是不甘心') }) -------------异步任务
. 异步任务之宏任务和微任务
- 宏任务:setTimeout、setInterval、setImmediate、script(整体代码)、 I/O 操作
- 微任务:process.nextTick、promise.then()
可以看出事件循环的本质如下:
js运行时,任务进入队列,先完成同步任务,后完成异步任务,而异步任务中先是完成微任务接着是完成宏任务。