范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

最全从输入URL到浏览器显示页面都发生了什么前端浏览器渲染流程

  面试中常被问到的问题,此问题包含web开发中从前端到后端到运维的绝大多数知识,主要考察面试者知识的广度。本文会根据作者了解的程度增加不断更新,不足之处欢迎评论区补充。
  首先了解一下URL的组成: http://www.baidu.com:8080/news/index.asp?boardID=5&ID=24618&page=1#name
  从上面的URL可以看出,一个完整的URL包括以下几部分:
  1、协议部分:该URL的协议部分为"http:",这代表网页使用的是HTTP协议。在Internet中可以使用多种协议,如HTTP,FTP等等本例中使用的是HTTP协议。在"HTTP"后面的"//"为分隔符
  2、域名部分:该URL的域名部分为"www.baidu.com"。一个URL中,也可以使用IP地址作为域名使用
  3、端口部分:跟在域名后面的是端口,域名和端口之间使用":"作为分隔符。端口不是一个URL必须的部分,如果省略端口部分,将采用默认端口80
  4、虚拟目录部分:从域名后的第一个"/"开始到最后一个"/"为止,是虚拟目录部分。虚拟目录也不是一个URL必须的部分。本例中的虚拟目录是"/news/"
  5、文件名部分:从域名后的最后一个"/"开始到"?"为止,是文件名部分,如果没有"?",则是从域名后的最后一个"/"开始到"#"为止,是文件部分,如果没有"?"和"#",那么从域名后的最后一个"/"开始到结束,都是文件名部分。本例中的文件名是"index.asp"。文件名部分也不是一个URL必须的部分,如果省略该部分,则使用默认的文件名
  6、锚部分:从"#"开始到最后,都是锚部分。本例中的锚部分是"name"。锚部分也不是一个URL必须的部分
  7、参数部分:从"?"开始到"#"为止之间的部分为参数部分,又称搜索部分、查询部分。本例中的参数部分为"boardID=5&ID=24618&page=1"。参数可以允许有多个参数,参数与参数之间用"&"作为分隔符。 URL的输入到浏览器解析的一系列事件
  很多大公司面试喜欢问这样一道面试题, 输入URL到看见页面发生了什么?  ,今天我们来总结一下。 简单来说,共有以下几个过程 DNS解析 发起TCP连接 发送HTTP请求 服务器处理请求并返回HTTP报文 浏览器解析渲染页面 连接结束。
  下面我们来看看具体的细节 通过DNS解析域名的实际IP地址
  发送至 DNS 服务器并获得域名对应的 WEB 服务器的 ip 地址。
  DNS 解析首先会从你的浏览器的缓存中去寻找是否有这个网址对应的 IP 地址,如果没有就向OS系统的 DNS 缓存中寻找,如果没有就是路由器的 DNS 缓存, 如果没有就是 ISP 的DNS 缓存中寻找。 所以,缓存的寻找过程就是: 浏览器 -> 系统 -> 路由器 -> ISP。 如果在某一个缓存中找到的话,就直接跳到下一步。 如果都没有找到的话,就会向 ISP 或者公共的域名解析服务发起 DNS 查找请求。这个查找的过程还是一个递归查询的过程。
  输入 www.google.com  网址后,首先在本地的域名服务器中查找,没找到去根域名服务器查找,没有再去 com  顶级域名服务器查找,,如此的类推下去,直到找到IP地址,然后把它记录在本地,供下次使用。大致过程就是 .   -> .com ->  google.com.   ->  www.google.com.  。 (你可能觉得我多写 .,并木有,这个.对应的就是根域名服务器,默认情况下所有的网址的最后一位都是.,既然是默认情况下,为了方便用户,通常都会省略,浏览器在请求DNS的时候会自动加上) DNS优化
  既然已经懂得了解析的具体过程,我们可以看到上述一共经过了N个过程,每个过程有一定的消耗和时间的等待,因此我们得想办法解决一下这个问题! DNS缓存
  DNS存在着多级缓存,从离浏览器的距离排序的话,有以下几种: 浏览器缓存,系统缓存,路由器缓存,IPS服务器缓存,根域名服务器缓存,顶级域名服务器缓存,主域名服务器缓存。
  在你的chrome浏览器中输入:chrome://dns/,你可以看到chrome浏览器的DNS缓存。
  系统缓存主要存在/etc/hosts(Linux系统)中
  检查浏览器是否有缓存
  通过 Cache-Control  和 Expires  来检查是否命中强缓存,命中则直接取本地磁盘的html(状态码为200 from disk(or memory) cache,内存or磁盘);
  如果没有命中强缓存,则会向服务器发起请求(先进行下一步的TCP连接),服务器通过 Etag  和 Last-Modify  来与服务器确认返回的响应是否被更改(协商缓存),若无更改则返回状态码(304 Not Modified),浏览器取本地缓存;
  若强缓存和协商缓存都没有命中则返回请求结果。 DNS负载均衡
  不知道你们有没有注意这样一件事,你访问http://baidu.com的时候,每次响应的并非是同一个服务器(IP地址不同),一般大公司都有成百上千台服务器来支撑访问,假设只有一个服务器,那它的性能和存储量要多大才能支撑这样大量的访问呢?DNS可以返回一个合适的机器的IP给用户,例如可以根据每台机器的负载量,该机器离用户地理位置的距离等等,这种过程就是DNS负载均衡 与 WEB 服务器建立 TCP 连接。
  TCP 协议通过三次握手建立连接。 客户端通过  SYN   报文段发送连接请求,确定服务端是否开启端口准备连接。状态设置为  SYN_SEND  ; 服务器如果有开着的端口并且决定接受连接,就会返回一个  SYN+ACK   报文段给客户端,状态设置为  SYN_RECV  ; 客户端收到服务器的  SYN+ACK   报文段,向服务器发送  ACK   报文段表示确认。此时客户端和服务器都设置为  ESTABLISHED   状态。连接建立,可以开始数据传输了。
  翻译成大白话就是: 客户端 :你能接收到我的消息吗? 服务端 :可以的,那你能接收到我的回复吗? 客户端 :可以,那我们开始聊正事吧。
  为什么是3次? :避免历史连接,确认客户端发来的请求是这次通信的人。
  为什么不是4次? :3次够了第四次浪费
  建立连接的过程是利用客户服务器模式,假设主机A为客户端,主机B为服务器端。
  采用三次握手是为了防止失效的连接请求报文段突然又传送到主机B,因而产生错误。失效的连接请求报文段是指:主机A发出的连接请求没有收到主机B的确认,于是经过一段时间后,主机A又重新向主机B发送连接请求,且建立成功,顺序完成数据传输。考虑这样一种特殊情况,主机A第一次发送的连接请求并没有丢失,而是因为网络节点导致延迟达到主机B,主机B以为是主机A又发起的新连接,于是主机B同意连接,并向主机A发回确认,但是此时主机A根本不会理会,主机B就一直在等待主机A发送数据,导致主机B的资源浪费。
  采用两次握手不行,原因就是上面说的失效的连接请求的特殊情况。而在三次握手中, client和server都有一个发syn和收ack的过程, 双方都是发后能收, 表明通信则准备工作OK.
  为什么不是四次握手呢? 大家应该知道通信中著名的蓝军红军约定, 这个例子说明, 通信不可能100%可靠, 而上面的三次握手已经做好了通信的准备工作, 再增加握手, 并不能显著提高可靠性, 而且也没有必要。 三次握手
  第一次握手 :
  客户端发送syn包(Seq=x)到服务器,并进入SYN_SEND状态,等待服务器确认;
  第二次握手:
  服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(Seq=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;
  第三次握手:
  客户端收到服务器的SYN ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
  握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。 若协议是https则会做加密
  HTTPS = HTTP + 加密 + 认证 + 完整性保护
  要先申请CA证书,并安装在服务器上(一个文件,配置nginx支持监听443端口开启ssl并设置证书路径)
  浏览器发送请求;
  网站从浏览器发过来的加密规则中选一组自身也支持的加密算法和hash算法,并向浏览器发送带有公钥的证书,当然证书还包含了很多信息,如网站地址、证书的颁发机构、过期时间等。
  浏览器解析证书。
  验证证书的合法性。如颁发机构是否合法、证书中的网站地址是否与访问的地址一致,若不合法,则浏览器提示证书不受信任,若合法,浏览器会显示一个小锁头。
  若合法,或用户接受了不合法的证书,浏览器会生成一串随机数的密码(即密钥),并用证书中提供的公钥加密。
  使用约定好的hash计算握手消息,并使用生成的随机数(即密钥)对消息进行加密,最后将之前生成的所有消息一并发送给网站服务器。
  网站服务器解析消息。用已有的私钥将密钥解密出来,然后用密钥解密发过来的握手消息,并验证是否跟浏览器传过来的一致。然后再用密钥加密一段握手消息,发送给浏览器。
  浏览器解密并计算握手消息的HASH,如果与服务端发来的HASH一致,此时握手过程结束,之后所有的通信数据将由之前浏览器生成的随机密码并利用对称加密算法进行加密。这里浏览器与网站互相发送加密的握手消息并验证,目的是为了保证双方都获得了一致的密码,并且可以正常的加密解密数据,为后续真正数据的传输做一次测试。
  发送HTTP请求
  首先科补一个小知识,HTTP的端口为80/8080,而HTTPS的端口为443
  发送HTTP请求的过程就是构建HTTP请求报文并通过TCP协议中发送到服务器指定端口 请求报文由 请求行 , 请求抱头 , 请求正文 组成。
  请求行
  请求行的格式为 Method Request-URL HTTP-Version CRLF    eg: GET index.html HTTP/1.1   常用的方法有:  GET  ,  POST  ,  PUT  ,  DELETE  ,  OPTIONS  ,  HEAD  。
  常见的请求方法区别
  这里主要展示 POST  和 GET  的区别
  常见的区别
  GET在浏览器回退时是无害的,而POST会再次提交请求。 GET产生的URL地址可以被Bookmark,而POST不可以。 GET请求会被浏览器主动cache,而POST不会,除非手动设置。 GET请求只能进行url编码,而POST支持多种编码方式。 GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。 GET请求在URL中传送的参数是有长度限制的,而POST么有。 对参数的数据类型,GET只接受ASCII字符,而POST没有限制。 GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。 GET参数通过URL传递,POST放在Request body中。
  注意一点你也可以在GET里面藏body,POST里面带参数
  重点区别
  GET  会产生一个 TCP  数据包,而 POST  会产生两个 TCP  数据包。
  详细的说就是: 对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据); 而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。
  注意一点,并不是所有的浏览器都会发送两次数据包,Firefox就发送一次
  请求报头
  请求报头允许客户端向服务器传递请求的附加信息和客户端自身的信息。
  从图中可以看出,请求报头中使用了Accept, Accept-Encoding, Accept-Language, Cache-Control, Connection, Cookie等字段。Accept用于指定客户端用于接受哪些类型的信息,Accept-Encoding与Accept类似,它用于指定接受的编码方式。Connection设置为Keep-alive用于告诉客户端本次HTTP请求结束之后并不需要关闭TCP连接,这样可以使下次HTTP请求使用相同的TCP通道,节省TCP连接建立的时间。
  请求正文
  当使用POST, PUT等方法时,通常需要客户端向服务器传递数据。这些数据就储存在请求正文中。在请求包头中有一些与请求正文相关的信息,例如: 现在的Web应用通常采用Rest架构,请求的数据格式一般为json。这时就需要设置 Content-Type: application/json  。
  更重要的事情-HTTP缓存
  HTTP属于客户端缓存,我们常认为浏览器有一个缓存数据库,用来保存一些静态文件,下面我们分为以下几个方面来简单介绍HTTP缓存 缓存的规则 缓存的方案 缓存的优点 不同刷新的请求执行过程
  缓存的规则
  缓存规则分为 强制缓存 和 协商缓存
  强制缓存
  当缓存数据库中有客户端需要的数据,客户端直接将数据从其中拿出来使用(如果数据未失效),当缓存服务器没有需要的数据时,客户端才会向服务端请求。
  协商缓存
  又称对比缓存。客户端会先从缓存数据库拿到一个缓存的标识,然后向服务端验证标识是否失效,如果没有失效服务端会返回304,这样客户端可以直接去缓存数据库拿出数据,如果失效,服务端会返回新的数据
  强制缓存
  对于强制缓存,服务器响应的header中会用两个字段来表明——Expires和Cache-Control。
  Expires
  Exprires的值为服务端返回的数据到期时间。当再次请求时的请求时间小于返回的此时间,则直接使用缓存数据。但由于服务端时间和客户端时间可能有误差,这也将导致缓存命中的误差,另一方面,Expires是HTTP1.0的产物,故现在大多数使用Cache-Control替代。
  Cache-Control
  Cache-Control有很多属性,不同的属性代表的意义也不同。 private:客户端可以缓存 public:客户端和代理服务器都可以缓存 max-age=t:缓存内容将在t秒后失效 no-cache:需要使用协商缓存来验证缓存数据 no-store:所有内容都不会缓存。
  协商缓存
  协商缓存需要进行对比判断是否可以使用缓存。浏览器第一次请求数据时,服务器会将缓存标识与数据一起响应给客户端,客户端将它们备份至缓存中。再次请求时,客户端会将缓存中的标识发送给服务器,服务器根据此标识判断。若未失效,返回304状态码,浏览器拿到此状态码就可以直接使用缓存数据了。
  对于协商缓存来说,缓存标识我们需要着重理解一下,下面我们将着重介绍它的两种缓存方案。
  Last-Modified
  Last-Modified:服务器在响应请求时,会告诉浏览器资源的最后修改时间。 if-Modified-Since  :浏览器再次请求服务器的时候,请求头会包含此字段,后面跟着在缓存中获得的最后修改时间。服务端收到此请求头发现有if-Modified-Since,则与被请求资源的最后修改时间进行对比,如果一致则返回304和响应报文头,浏览器只需要从缓存中获取信息即可。
  从字面上看,就是说:从某个时间节点算起,是否文件被修改了 如果真的被修改:那么开始传输响应一个整体,服务器返回:200 OK 如果没有被修改:那么只需传输响应header,服务器返回:304 Not Modified if-Unmodified-Since  :从字面上看, 就是说: 从某个时间点算起, 是否文件没有被修改 如果没有被修改:则开始`继续"传送文件: 服务器返回: 200 OK 如果文件被修改:则不传输,服务器返回: 412 Precondition failed (预处理错误)
  这两个的区别是一个是修改了才下载一个是没修改才下载。
  Last-Modified 说好却也不是特别好,因为如果在服务器上,一个资源被修改了,但其实际内容根本没发生改变,会因为Last-Modified时间匹配不上而返回了整个实体给客户端(即使客户端缓存里有个一模一样的资源)。为了解决这个问题,HTTP1.1推出了Etag。
  Etag
  Etag:服务器响应请求时,通过此字段告诉浏览器当前资源在服务器生成的唯一标识(生成规则由服务器决定) If-None-Match:再次请求服务器时,浏览器的请求报文头部会包含此字段,后面的值为在缓存中获取的标识。服务器接收到次报文后发现If-None-Match则与被请求资源的唯一标识进行对比。 不同,说明资源被改动过,则响应整个资源内容,返回状态码200。 相同,说明资源无心修改,则响应header,浏览器直接从缓存中获取数据信息。返回状态码304.
  但是实际应用中由于Etag的计算是使用算法来得出的,而算法会占用服务端计算的资源,所有服务端的资源都是宝贵的,所以就很少使用Etag了。
  缓存的优点 减少了冗余的数据传递,节省宽带流量 减少了服务器的负担,大大提高了网站性能 加快了客户端加载网页的速度 这也正是HTTP缓存属于客户端缓存的原因。
  不同刷新的请求执行过程
  浏览器地址栏中写入URL,回车 浏览器发现缓存中有这个文件了,不用继续请求了,直接去缓存拿。(最快)
  F5 F5就是告诉浏览器,别偷懒,好歹去服务器看看这个文件是否有过期了。于是浏览器就战战兢兢的发送一个请求带上If-Modify-since。
  Ctrl+F5 告诉浏览器,你先把你缓存中的这个文件给我删了,然后再去服务器请求个完整的资源文件下来。于是客户端就完成了强行更新的操作.
  服务器处理请求并返回HTTP报文
  它会对TCP连接进行处理,对HTTP协议进行解析,并按照报文格式进一步封装成HTTP Request对象,供上层使用。这一部分工作一般是由Web服务器去进行,我使用过的Web服务器有Tomcat, Nginx和Apache等等 HTTP报文也分成三份, 状态码  , 响应报头 和 响应报文
  状态码
  状态码是由3位数组成,第一个数字定义了响应的类别,且有五种可能取值: 1xx:指示信息–表示请求已接收,继续处理。 2xx:成功–表示请求已被成功接收、理解、接受。 3xx:重定向–要完成请求必须进行更进一步的操作。 4xx:客户端错误–请求有语法错误或请求无法实现。 5xx:服务器端错误–服务器未能实现合法的请求。
  平时遇到比较常见的状态码有:200, 204, 301, 302, 304, 400, 401, 403, 404, 422, 500
  常见状态码区别
  200 成功
  请求成功,通常服务器提供了需要的资源。
  204 无内容
  服务器成功处理了请求,但没有返回任何内容。
  301 永久移动
  请求的网页已永久移动到新位置。 服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。
  302 临时移动
  服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。
  304 未修改
  自从上次请求后,请求的网页未修改过。 服务器返回此响应时,不会返回网页内容。
  400 错误请求
  服务器不理解请求的语法。
  401 未授权
  请求要求身份验证。 对于需要登录的网页,服务器可能返回此响应。
  403 禁止
  服务器拒绝请求。
  404 未找到
  服务器找不到请求的网页。
  422 无法处理
  请求格式正确,但是由于含有语义错误,无法响应
  500 服务器内部错误
  服务器遇到错误,无法完成请求。
  响应报头
  常见的响应报头字段有: Server, Connection...。
  响应报文
  你从服务器请求的HTML,CSS,JS文件就放在这里面 浏览器解析渲染页面
  就是 Webkit  解析渲染页面的过程。 解析HTML形成DOM树 解析CSS形成CSSOM 树 合并DOM树和CSSOM树形成渲染树 浏览器开始渲染并绘制页面
  这个过程涉及两个比较重要的概念 回流 和 重绘 ,DOM结点都是以盒模型形式存在,需要浏览器去计算位置和宽度等,这个过程就是回流。等到页面的宽高,大小,颜色等属性确定下来后,浏览器开始绘制内容,这个过程叫做重绘。浏览器刚打开页面一定要经过这两个过程的,但是这个过程非常非常非常消耗性能,所以我们应该尽量减少页面的回流和重绘 浏览器解析执行js脚本
  这个过程中可能会有dom操作、ajax发起的http网络请求等。 浏览器发起网络请求
  web-socket、ajax等,这个过程通常是为了获取数据 服务器响应ajax请求ajax请求在到达真正的server之前,可能还会经过网关全线校验、消息队列或nginx等负载均衡处理 到达server后,后端会解析http请求报文,得到url、请求参数、http头、cookie等等信息 登录校验、权限校验(cookie校验、jwt权限校验等) 可能会查询数据库,进行常用的CRUD(增删改查)等操作 返回响应数据 浏览器处理事件循环等异步逻辑。
  setTimeout、setInterval、Promise等宏任务、微任务队列 性能优化之回流重绘回流
  当Render Tree中部分或全部元素的尺寸、结构、或某些属性发生改变时,浏览器重新渲染部分或全部文档的过程称为回流。
  会导致回流的操作: 页面首次渲染 浏览器窗口大小发生改变 元素尺寸或位置发生改变 元素内容变化(文字数量或图片大小等等) 元素字体大小变化 添加或者删除可见的DOM元素 激活CSS伪类(例如::hover) 查询某些属性或调用某些方法
  一些常用且会导致回流的属性和方法: clientWidth、clientHeight、clientTop、clientLeft  offsetWidth、offsetHeight、offsetTop、offsetLeft  scrollWidth、scrollHeight、scrollTop、scrollLeft  scrollIntoView()、scrollIntoViewIfNeeded()  getComputedStyle()  getBoundingClientRect()  scrollTo()  重绘
  当页面中元素样式的改变并不影响它在文档流中的位置时(例如:color、background-color、visibility等),浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘。 优化CSS避免使用table布局。 尽可能在DOM树的最末端改变class。 避免设置多层内联样式。 将动画效果应用到position属性为absolute或fixed的元素上。 避免使用CSS表达式(例如:calc())。 JavaScript避免频繁操作样式,最好一次性重写style属性,或者将样式列表定义为class并一次性更改class属性。 避免频繁操作DOM,创建一个documentFragment,在它上面应用所有DOM操作,最后再把它添加到文档中。 也可以先为元素设置display: none,操作结束后再把它显示出来。因为在display属性为none的元素上进行的DOM操作不会引发回流和重绘。 避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。 对具有复杂动画的元素使用绝对定位,使它脱离文档流,否则会引起父元素及后续元素频繁回流。 JS的解析
  JS的解析是由浏览器的JS引擎完成的。由于JavaScript是单线程运行,也就是说一个时间只能干一件事,干这件事情时其他事情都有排队,但是有些人物比较耗时(例如IO操作),所以将任务分为 同步任务 和 异步任务 ,所有的同步任务放在主线程上执行,形成执行栈,而异步任务等待,当执行栈被清空时才去看看异步任务有没有东西要搞,有再提取到主线程执行,这样往复循环(冤冤相报何时了,阿弥陀佛),就形成了Event Loop事件循环,下面来看看大人物 Event Loop
  先看一段代码 setTimeout(function(){     console.log("定时器开始啦") });  new Promise(function(resolve){     console.log("马上执行for循环啦");     for(var i = 0; i < 10000; i++){         i == 99 && resolve();     } }).then(function(){     console.log("执行then函数啦") });  console.log("代码执行结束");
  结果我想大家都应该知道。主要来介绍JavaScript的解析,至于Promise等下一节再说 JavaScript
  JavaScript是一门单线程语言,尽管H5中提出了 Web-Worker  ,能够模拟实现多线程,但本质上还是单线程,说它是多线程就是扯淡。 事件循环
  既然是单线程,每个事件的执行就要有顺序,比如你去银行取钱,前面的人在进行,后面的就得等待,要是前面的人弄个一两个小时,估计后面的人都疯了,因此,浏览器的JS引擎处理JavaScript时分为 同步任务 和 异步任务
  这张图我们可以清楚看到 同步和异步任务分别进入不同的执行"场所",同步的进入主线程,异步的进入Event Table并注册函数。 当指定的事情完成时,Event Table会将这个函数移入Event Queue。 主线程内的任务执行完毕为空,会去Event Queue读取对应的函数,进入主线程执行。 上述过程会不断重复,也就是常说的Event Loop(事件循环)。
  js引擎存在monitoring process进程,会持续不断的检查主线程执行栈是否为空,一旦为空,就会去Event Queue那里检查是否有等待被调用的函数。 估计看完这些你对事件循环有一定的了解,但是事实上我们看对的没这么简单,通常我们会看到Promise,setTimeout,process.nextTick(),这个时候你和我就懵逼。
  除了同步任务和异步任务,我们还分为宏任务和微任务,常见的有以下几种 macro-task(宏任务):包括整体代码script,setTimeout,setInterval micro-task(微任务):Promise,process.nextTick
  不同任务会进入不同的任务队列来执行。 JS引擎开始工作后,先在宏任务中开始第一次循环( script里面先执行,不过我喜欢把它拎出来,直接称其进入执行栈  ),当主线程执行栈全部任务被清空后去微任务看看,如果有等待执行的任务,执行全部的微任务(其实将其回调函数推入执行栈来执行),再去宏任务找最先进入队列的任务执行,执行这个任务后再去主线程执行任务(例如执行```console.log("hello world")这种任务),执行栈被清空后再去微任务,这样往复循环(冤冤相报何时了)
  Tip:微任务会全部执行,而宏任务会一个一个来执行
  下面来看一段代码 setTimeout(function() {     console.log("setTimeout"); })  new Promise(function(resolve) {     console.log("promise");     resolve(); }).then(function() {     console.log("then"); })  console.log("console");
  我们看看它的执行情况 第一轮 这段代码进入主线程 遇到setTimeout,将其回调函数注册后分发到宏任务 第二轮 遇到Promise,new Promise立即执行(这个不解释,想了解的我后续文章会介绍),输出 promise  ,遇到 then  ,将其分发到微任务 第三轮 遇到 console.log("console")  ,直接输出 console  第四轮 主线程执行栈已经清空,先去微任务看看,执行then函数,输出 then  第五轮 微任务执行完了,看看宏任务,有个setTimeout,输出 setTimeout  ,整体执行完毕。
  具体的执行过程大致就是这样。

联想还是脸响(打的脸响)?最近看了许多关于司马南与联想互撕的新闻以及一些所谓的名人自媒体对这场论战的发言!下面本人就发表一下我一个普通打工人的愚见!!!首先非常敬佩司马南先生,因为他敢于说出自己心中的疑问,埃隆马斯克终将成为下一个乔布斯本文只是站在理性的角度进行分析,带有大量个人观点。距离乔布斯去世有几年了,究竟谁会成为类似乔布斯这类科技界的领军人物呢?结合这些人所领导的企业分析,最有可能成为领军人物的我认为是马没有退路就是胜利之路,华为加油近日,华为举行军团组建成立大会,77岁的任正非说了一番铁血的话,他说和平是打出来的,没有退路就是胜利之路,我们要用艰苦奋斗,英勇牺牲,打出未来30年的一个和平环境,让任何人都不敢再如果取消二维码支付,你觉得我们的生活将面临怎样的改变?如果取消二维码,会给现实生活带来诸多不便。因为随着时代的发展,人们已经习惯用二维码扫码付款,大部分人都已经很少装现金出门。比如拿我来说吧,我基本不带现金出门,互联网时代,确实给我们从4299元降至2699元,无线充电顶级芯片,老旗舰机还值得买吗?消费电子买新不买旧如果猜的没错的话,题主说的是魅族17Pro吧这个款手机是去年发布的,目前这款手机的8128GB版本已经从4299元降至2699元。先看硬件,三星定制SuperAM打死我也想不到美团测试面试题这么难,当场给我吓die了前言不知道你们多长时间没有参加过面试了,最近这段时间的面试,真的是一个比一个严格!昨天参加了一线大厂的技术面,当场给我吓die了,没想到这么难!如果你不信,你也来diedie1CP小华为诞生,高端芯片已突破,王传福表态外国人,不卖今年,芯片短缺成为了很多人关注的焦点,这是自芯片被发明出来半个多世纪以来第一次出现大规模供应短缺现象。早在2020年第四季度开始,芯片就出现了大缺货的趋势。随着时间的推进,芯片短缺微信支付运营主体腾讯财付通回应外汇业务违规被罚278万元IT之家11月28日消息,近日,国家外汇管理局深圳市分局发布一批行政处罚决定,微信支付的运营主体财付通支付科技有限公司深圳农村商业银行股份有限公司等均在其中。国家外汇管理局深圳市分日媒中企借电动汽车逆袭而来新华社北京11月28日电参考消息日前刊登源自日本经济新闻网站的报道中企凭借电动汽车实现逆袭。报道摘要如下9月底,中国新兴电动汽车企业蔚来汽车开始在挪威发售最新款电动汽车。该公司将登流量卡是真实的吗?不知道题主说的流量卡是否是那种0月租流量随用随充没有手机号的卡?如果是,那就需要说一下,那不是什么流量卡,而是自动售货机等使用的物联卡,这种卡按规定不得用于手机平板等智能设备(原因不吹不黑,4年前发布的iPhoneX,相当于现在什么档次的安卓机?标题已经在吹了档位仍旧相当于现在的顶级机皇犹记得,2017年末那会好多同事趁着去香港旅游,顺便购买港版iPhoneX(7k多一点的价格)。这一现象风靡了好一阵子。当年还在大厂上班,
商用自动洗碗机的特点自动洗碗机的功能正在逐步完善可替代人工清洗消毒柜烘干等。自动洗碗机具有自动排渣自动清洗自动烘干自动消毒等功能。它可以用电或蒸汽加热。绿色环保无污染节能无燃烧排放无辐射。它比传统洗碗实力藏不住!FindX2这屏幕效果感受一下,苹果都被比下去屏幕作为我们使用手机的主要载体,其重要性也与日俱增。今年以来,市场上就出现了多部搭载120Hz屏幕的机型,其中又以OPPOFindX2Pro的关注度最高,它凭借着120Hz刷新率32021年中国消费者全健康需求洞察健康需求丨洞察报告核心摘要概念定义全健康,OneHealth,是系统性地思考和研究人类健康动物健康以及环境健康的新策略新方法和新学科,它强调全生态全产业链的健康,覆盖用户健康雇员健樱桃在天使与淑女之间的轮回天使幻化人间,世人注入万般风情,无人能说得清天使的模样,但她的传世之爱,她的倾城之美,却有无数种诠释。樱桃很少穿白色的衣服,更多地是暖色调的服饰,风格上趋向于欧美时尚,这与她早年常成都车展欧拉首款纯电SUV,命名樱桃猫最高续航600km!提到欧拉汽车,我们第一时间能够想到黑猫白猫这样的车型。根据欧拉官方信息显示,在今年8月29号正式开展的成都车展上,家族首款纯电动SUV会跟我们正式见面,新车名字非常可爱,叫做樱桃猫你的第一台敞篷跑车?保时捷718Boxster实拍很多人都会幻想着一天能拥有一辆敞篷跑车,在黄昏的阳光下,开启敞篷,带上一副墨镜,享受着敞篷的开扬感以及车辆给我的驾驶乐趣。当我在停车场看见它,已经中毒了,颜值太帅了,这款保时捷71如何洗杯没有异味?经测试后,使用自动洗杯机的综合成本约为人工洗涤的综合成本的50。通过节能的洗杯杯,只需23人可以轻松处理高峰期的酒杯洗涤工作,价格相对较低,从而节省了大量的人力和时间。作为管理者,商用长龙式洗碗机的特点在洗碗机刚进入餐饮行业时,市场上的商用洗碗机多以揭盖式为主,随着市场经济的发展,长龙洗碗机以其不可替代的优势应用于餐饮厨房。长龙式商用洗碗机的优势是什么?适用于哪些场景?长龙式洗碗自动洗筐机的性能和特点洗筐机由人工送入设备链条轨道进行热碱喷淋热水喷淋清水循环喷淋。箱体在传动链的传动下用三段高压水喷淋清洗,烘干段可根据客户需要增加。用三把风刀对箱体进行脱水,除去大部分水滴,然后利用酒店后厨洗碗机在酒店餐饮厨房,使用商务酒店洗碗机可以大大改善工作条件,以及提高工作效率,改进餐具洗干净的效果,所以洗碗机的普及是社会发展的必然趋势。商务酒店洗碗机目前占据酒店行业较大的市场,而相商用洗碗机的基本维护常识1。如果长时间不使用洗碗机,将温水清洁内腔的油渍残留,然后用干布擦干水分,并存放在通风干燥处。商用洗碗机的使用与人工手洗相比,可以有效避免卫生风险的安全性,以确保健康安全,大大提高