浏览器 事件循环(Event Loop)

来看一段代码:

function eat() {

console.log(‘吃东西啦’)

setTimeout(drink, 1000);

console.log(‘吃饱喝足啦’)

}

function drink() {

console.log(‘饮茶啦’)

}

eat()

这里的eat是同步任务,而setTimeout是异步任务,当执行到jsetTimieout时,会将它挂起,直到一秒后将它的回调函数drink添加到任务队列中等待执行。所以,这里的执行结果就会变成这样:

在这里插入图片描述

  • task queue (任务队列)

事件循环有一个或多个任务队列。任务队列是一组任务,而不是一个队列。因为事件循环处理模型的第一步是从任务队列中选择一个可运行的任务,而不是直接拿第一个任务。规范是这么写的:

Task queues are sets, not queues, because step one of the event loop processing model grabs the first runnable task from the chosen queue, instead of dequeuing the first task.

看到这个规范我是有点迷的,以前一直认为任务队列就是一个队列,遵循先进先出的规则的,很多技术文章也是这么写的。这里如果有更好的理解,欢迎评论区留言。

接下来看一张大名鼎鼎的图:

在这里插入图片描述

这是演讲菲利普·罗伯茨:到底什么是Event Loop呢里的一张图。(可以去看下这个演讲,有不忍吐槽的中文字幕,不过要个梯子)遗憾的是,里面并没有讲到宏任务和微任务。

看下代码:

console.log(1)

setTimeout(cb, 2000)

console.log(3)

function cb() {

console.log(2)

}

按照图片的理解,这里就是这么运行的:

1、将console.log(1)压入调用栈中,执行完毕,然后弹出

2、setTimeout压入栈中,发现是异步任务,交给浏览器的其他线程,将他挂起

3、将console.log(3)压入栈中,执行完毕,弹出

4、这时候调用栈是空的,会轮询任务队列里面有没有任务,而如果第二步挂起的setTimeout的两秒还没有过,这时候任务队列就是空的,不执行。只有两秒到了,将cb函数压入任务队列中,事件轮询发现任务队列里面有任务,这时候cb才会被压入栈中执行。

5、以上过程不断重复,也就形成了事件循环。

所以打印的结果就是:

在这里插入图片描述

我们知道,js是单线程的,同一时间能且只能做一件事件,那这些事件的挂起,轮询只能交给浏览器的其他线程去完成了。所以说,是宿主环境给了js异步执行的能力。

  • 宏任务(macrotask)

macroTask,我并没有在规范中找到相关的介绍。不过其他的技术文章有两种说法,一个说法是将任务队列分为宏任务队列和微任务队列,另一个就是说宏任务队列就是任务队列。我个人更偏向于第二种说法,原因稍后说明。

  • 微任务(microtask)

微任务队列不是任务队列,规范是这么说的:

The microtask queue is not a task queue.

这也是上面说的我偏向于第二种说法的原因。每个事件循环都有一个微任务队列,当调用栈为空的时候就会调用微任务队列里面的任务。事件循环一开始微任务队列是空的,过程中会有微任务添加进去,而当主线程为空时,就会执行微任务队列里面的任务。

那哪些宏任务,哪些是微任务呢?没有找到相关的规范文档。不过按照其他的技术文章,一般是这么分类的:

宏任务: script(整体代码),setTimeout, setInterval, setImmediate,I/O, UI rendering

微任务: promise().then, Object.observe, MutationObserver

运行流程

我们来看一下代码:

1、首先,这段代码会作为宏任务而被添加到宏任务队列里面。这时候,宏任务队列只有一个任务,主线程为空,执行这个任务。

2、console.log(1)入栈,打印1,执行完毕,出栈

3、setTimeout入栈,挂起,等待200ms后将回调函数添加到宏任务队列

这里分享一份由字节前端面试官整理的「2021大厂前端面试手册」,内容囊括Html、CSS、Javascript、Vue、HTTP、浏览器面试题、数据结构与算法。全部整理在下方文档中,共计111道

HTML

  • HTML5有哪些新特性?

  • Doctype作⽤? 严格模式与混杂模式如何区分?它们有何意义?

  • 如何实现浏览器内多个标签页之间的通信?

  • ⾏内元素有哪些?块级元素有哪些? 空(void)元素有那些?⾏内元 素和块级元素有什么区别?

  • 简述⼀下src与href的区别?

  • cookies,sessionStorage,localStorage 的区别?

  • HTML5 的离线储存的使用和原理?

  • 怎样处理 移动端 1px 被 渲染成 2px 问题?

  • iframe 的优缺点?

  • Canvas 和 SVG 图形的区别是什么?

JavaScript

  • 问:0.1 + 0.2 === 0.3 嘛?为什么?

  • JS 数据类型

  • 写代码:实现函数能够深度克隆基本类型

  • 事件流

  • 事件是如何实现的?

  • new 一个函数发生了什么

  • 什么是作用域?

  • JS 隐式转换,显示转换

  • 了解 this 嘛,bind,call,apply 具体指什么

  • 手写 bind、apply、call

  • setTimeout(fn, 0)多久才执行,Event Loop

  • 手写题:Promise 原理

  • 说一下原型链和原型链的继承吧

  • 数组能够调用的函数有那些?

  • PWA使用过吗?serviceWorker的使用原理是啥?

  • ES6 之前使用 prototype 实现继承

  • 箭头函数和普通函数有啥区别?箭头函数能当构造函数吗?

  • 事件循环机制 (Event Loop)

  • 19
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值