面试题-部分

news2024/9/27 20:07:05

目录

1. 从输入url到渲染页面,中间经历了什么?

2. vue中的v-if和v-show有什么区别

3. 什么是Css中的回流(重排)与重绘

4. 介绍一下let、const、var的区别

5. 箭头函数和普通函数有什么区别

6. Css中常用的水平垂直居中解决方案有哪些

7. 什么是BFC

怎样触发BFC

BFC的特点和用途

8. localStorage,sessionStorage,cookies的区别

9. 常用的跨域解决方案有哪些

10. Js中的单线程和事件循环

11. Vue2与Vue3中的双向数据绑定

12. React Hook为什么不能放到条件语句中?

13. React有哪些常用的hooks?

14. Promise 是什么?有什么用途?

14.1. 为什么要使用 Promise?

14.2. 什么是 Promise?

14.3. 如何使用 Promise?

14.4. Promise 的三种状态

14.5. 使用 .then() 处理异步结果

14.6. 链式调用

14.7. 错误处理

14.8. finally() 方法

14.9. 什么是 async/await?

14.10. 总结

15. 浏览器中的事件循环 (Event Loop)

15.1. 同步 (synchronous) 与异步 (asynchronous)

15.2. 事件循环 (Event loop) 的组成 - 执行栈和任务队列

15.3. 事件循环 (Event loop) 的步骤

15.4. 宏任务 (Macro Task) 与微任务 (Micro Task)

1. 从输入url到渲染页面,中间经历了什么?

  1. 浏览器的地址栏输入URL并按下回车。
  2. 浏览器查找当前URL是否存在缓存,并比较缓存是否过期。
  3. DNS解析URL对应的IP。
  4. 根据IP建立TCP连接(三次握手)。
  5. HTTP发起请求。
  6. 服务器处理请求,浏览器接收HTTP响应。
  7. 渲染页面,构建DOM树。
  8. 关闭TCP连接(四次挥手)

从输入URL到最终页面渲染的过程涉及多个步骤,包括域名解析、建立连接、服务器响应、页面下载和页面渲染等。

1.域名解析:当用户在浏览器中输入URL时,浏览器会首先解析该URL,获取其中的域名,并向DNS服务器发送解析请求,获取该域名对应的服务器IP地址。

2.建立连接:浏览器根据获取的IP地址,向服务器发起连接请求。如果连接成功,浏览器将与服务器建立TCP连接。

3.服务器响应:一旦建立了连接,浏览器会向服务器发送HTTP请求,请求特定页面的数据。服务器接收到请求后,会根据请求的内容和服务器上的资源,生成相应的HTTP
响应,并将其发送回给浏览器。

4.页面下载:浏览器接收到来自服务器的HTTP响应后,会解析响应头和响应体,从中提取页面所需的资源(如HTML、CSS、JavaScript、图片等),并将这些资源下载到本地的缓存中。

5.页面渲染:页面所需的资源下载完毕后,浏览器会根据HTML结构和CSS样式对页面进行解析和渲染,JavaScript代码将被执行以处理页面交互和动态效果。构建DOM树,最终
,页面被渲染出来,并展示给用户。

总的来说,从输入URL到最终页面渲染,涉及了域名解析、建立连接、服务器响应、页面下载和页面渲染等多个步骤,这些步骤共同构成了用户访问网页的完整过程。

三次握手:

客户端向服务器发送一个SYN包(同步请求)以建立连接。
服务器接收到SYN包后,返回一个ACK包(确认)以表示接收到了客户端的连接请求,并发送自己的SYN包以建立连接。
客户端接收到服务器的ACK包和SYN包后,返回一个ACK包以确认建立连接。

四次挥手:

客户端向服务器发送一个FIN包(关闭连接请求)以表示客户端不再发送数据。
服务器接收到客户端的FIN包后,返回一个ACK包以确认收到了关闭连接请求。
服务器完成在发送数据后向客户端发送一个FIN包以关闭连接。
客户端接收到服务器的FIN包后,返回一个ACK包以确认关闭连接。此时连接关闭。

2. vue中的v-if和v-show有什么区别

v-if和v-show都是在Vue中用来控制元素显示与隐藏的指令,但是它们之间有一些区别:

v-if是真正的条件渲染,即如果条件为false,则该元素不会被渲染到DOM中;而v-show仅仅是通过CSS的display属性来控制元素的显示和隐藏,元素始终会被渲染到DOM中。

当页面中的元素频繁切换显示与隐藏时,使用v-show会比v-if性能更好,因为v-show只是切换CSS的display属性,而v-if需要频繁地添加和移除DOM元素,会引起重排。

因此,如果元素的显示与隐藏频繁变化,可以使用v-show来提升性能,如果元素的显示与隐藏是由条件决定的,并且不频繁变化,可以使用v-if来实现条件渲染。

3. 什么是Css中的回流(重排)与重绘

  • 回流(重排)指的是当页面中的元素发生布局或几何属性发生变化时,浏览器需要重新计算这些元素的位置和大小,然后重新构建页面的渲染树,这个过程称为回流。由于需要重新计算布局,回流的代价很大,会对页面的性能产生负面影响。
  • 重绘指的是当页面中的元素样式发生改变时,浏览器会重新绘制这些元素的外观,但不会改变它们在页面中的位置和大小。重绘的代价相对较小,但仍然会对页面性能产生一定的影响.

在Vue中,通过条件渲染指令v-if和v-else-if来动态控制元素的显示和隐藏。可以影响页面的重排。当 v-if 的条件从 false 变为 true 时,被包裹的元素会从 DOM 中移除,而当条件从 true 变为 false 时,被包裹的元素会重新插入到 DOM 中去。这种操作会导致页面发生重排。因此,如果需要避免页面重排,可以考虑使用 v-show 指令,它在条件变化时只是控制元素的 display 样式,不会影响到 DOM 结构。

4. 介绍一下let、const、var的区别

在JavaScript中,let、const和var都是用来声明变量的关键字,它们之间有一些重要的区别。

  • var:

使用var声明的变量属于函数作用域或全局作用域,而不是块级作用域。这意味着在if语句、循环或函数内部声明的var变量可以在外部访问。

var声明的变量可以被重复声明,而不会产生错误。

var变量可以被提升,即在代码执行过程中变量声明会被提升到函数或全局作用域的顶部。

  • let:

使用let声明的变量属于块级作用域,只在声明的块内部有效。这意味着if语句、循环或函数内部声明的let变量在外部是不可访问的。

let声明的变量不可以被重复声明,如果重复声明同一个变量会产生错误。

  • const:

使用const声明的变量也属于块级作用域,同样只在声明的块内部有效。

const声明的变量必须被初始化,并且不能被重新赋值。这意味着一旦const变量被赋值,就不能再被修改。

const保证的并不是变量的值不能改动,而是变量指向的那个内存地址不能改动。对于基本类型的数据(数值、字符串、布尔值),其值就保存在变量指向的那个内存地址,因此等同于常量。

但对于引用类型的数据(主要是对象和数组)来说,变量指向数据的内存地址,保存的只是一个指针,const只能保证这个指针是固定不变的,至于它指向的数据结构是不是可变的,就完全不能控制了

总的来说,let和const相对于var是更加安全和可控的变量声明方式,能够避免一些常见的问题和错误。而const则更为严格,要求变量在声明时必须被初始化,并且不能被重新赋值。因此在开发中,推荐优先使用let和const来声明变量,避免使用var。

5. 箭头函数和普通函数有什么区别

  1. 写法不同:箭头函数使用箭头(=>)来定义,适用于匿名函数场景,而普通函数使用 function 关键字定义。
  2. this 的处理方式不同:在箭头函数中,this 的值与外层作用域的 this 绑定。而在普通函数中,this 的值由调用该函数的方式决定。
  3. 箭头函数没有 arguments 对象:箭头函数中没有自己的 arguments 对象,它的参数只能通过参数列表来传递。
  4. 箭头函数不能用作构造函数:由于箭头函数中没有自己的 this 值,因此不能用作构造函数来创建对象实例。
  5. 箭头函数没有prototype

箭头函数和普通函数的主要区别在于它们的语法和作用域。

语法:箭头函数使用箭头符号(=>)来定义函数,而普通函数使用关键字function来定义函数。

作用域:箭头函数没有自己的this,它会捕获其所在上下文的this值。而普通函数有自己的this,它的值在函数被调用时由调用方式决定。

参数:箭头函数只能包含一个表达式,如果需要多行语句或者语句块,需要使用大括号来定义函数体。而普通函数可以包含任意数量的语句和语句块。

总的来说,箭头函数更简洁,适合于单一的表达式或者语句,而普通函数更灵活,可以包含更多的逻辑和控制结构。选择使用哪种函数取决于具体的需求和使用场景。

6. Css中常用的水平垂直居中解决方案有哪些

  1. 使用Flexbox布局
.container {
  display: flex;
  align-items: center;
  justify-content: center;
}
  1. 使用Grid布局
.container {
  display: grid;
  place-items: center;
}
  1. 使用绝对定位和transform属性
.container {
  position: relative;
}

.item {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
  1. 使用表格布局
.container {
  display: table;
}

.item {
  display: table-cell;
  text-align: center;
  vertical-align: middle;
}
  1. 使用CSS网格布局
.container {
  display: grid;
  justify-items: center;
  align-items: center;
}

这些方法都可以实现水平和垂直居中,选择适合自己项目的解决方案即可。

7. 什么是BFC

BFC(Block Formatting Context)是 CSS 中一个很重要的概念。它是指一个块级容器,其中的元素按照特定规则布局和渲染,同时也影响着其内部和外部元素的布局。

BFC 全称:Block Formatting Context, 名为 “块级格式化上下文”。

W3C官方解释为:BFC它决定了元素如何对其内容进行定位,以及与其它元素的关系和相互作用,当涉及到可视化布局时,Block Formatting Context提供了一个环境,HTML在这个环境中按照一定的规则进行布局。

简单来说就是,BFC是一个完全独立的空间(布局环境),让空间里的子元素不会影响到外面的布局。那么怎么使用BFC呢,BFC可以看做是一个CSS元素属性

怎样触发BFC

这里简单列举几个触发BFC使用的CSS属性

  • 根元素(HTML) :浏览器的元素所产生的盒子本身就是BFC区域 (了解即可,用不上)
  • 设置float属性
  • 设置overflow属性(属性值不为visible即可)
  • 设置position属性(属性值需要是absolute或fixed)
  • 设置display属性值为inline-block、flow-root、flex
  • 多列容器(column-count)
  • 表格元素(table thead tbody tfoot tr th td caption)
  • column-span为all的元素(表格第一行横跨所有列)

BFC的特点和用途

用途:

  • 解决浮动和定位元素引起的布局问题。
  • 实现自适应布局和响应式设计。
  • 改善文本排版和可读性。

特点:

  • BFC就是一个块级元素,块级元素会在垂直方向一个接一个的排列
  • BFC就是页面中的一个隔离的独立容器,容器里的标签不会影响到外部标签
  • 垂直方向的距离由margin决定, 属于同一个BFC的两个相邻的标签外边距会发生重叠
  • BFC 可以包含浮动元素,并确保它们不影响其他元素的布局。

8. localStorage,sessionStorage,cookies的区别

localStorage,sessionStorage和cookies都是在客户端存储数据的方式。

  • localStorage:

存储容量:一般来说,localStorage的存储容量是比较大的,可以存储几MB的数据。

持久性:localStorage中的数据是持久性的,即使用户关闭浏览器或者重启计算机,数据也会保留。

作用域:localStorage中的数据是在同一个域名下共享的。

  • sessionStorage:

存储容量:sessionStorage的存储容量一般比较小,通常是5MB左右。

持久性:sessionStorage中的数据是会话性的,即当用户关闭标签页或者浏览器时,数据会被清除。

作用域:sessionStorage中的数据也是在同一个域名下共享的。

  • Cookies:

存储容量:cookies的存储容量一般比较小,通常是几KB的数据。

持久性:cookies中的数据可以设置过期时间,可以是会话性的,也可以是持久性的。

作用域:cookies中的数据可以在同一个域名下共享,同时也可以通过设置路径来限制作用域。

区别:

1、存储空间:cookie存储空间最小、只有4kb、但是http请求中可以携带cookie,loacalstorage、sessionstorage存储空间5m或更大

2、有效期:cookie不设置时间、关闭游览器销毁,sessionstorage关闭游览器(窗口或者标签页)销毁,loacalstorage不手动清除一直保留

3、作用域:sessionStorage不在不同游览器窗口(标签页)共享、即使同源,cookie、localstorage在所有同源窗口之间共享

9. 常用的跨域解决方案有哪些

  • JSONP (JSON with Padding):利用script标签的src属性不受同源策略限制的特性,通过动态创建script标签,向其他域名请求数据并传递回调函数,实现跨域请求。
  • CORS (跨域资源共享):在服务器端设置响应头,允许指定的源或所有源的请求访问资源,实现跨域访问。
  • 代理服务器:在自己的域下设置一个代理服务器,然后在代理服务器上请求其他域的资源,再将结果返回给客户端。这样客户端就不会遇到跨域问题了。
  • postMessage:通过window.postMessage方法在不同窗口间进行跨域通信,实现数据传递。
  • 服务器端转发:在同源服务器上设置一个接口,将前端的跨域请求转发到其他域名的真正数据接口,再将数据返回给前端。
  • WebSocket:WebSocket 是一种 HTML5 协议,它使得浏览器和服务器之间可以建立持久化的连接,可以直接使用 Socket 进行通信,避免了浏览器的跨域限制。
  • Nginx反向代理:利用Nginx的反向代理功能,在同一域下转发请求到目标服务器,从而实现跨域请求。
  • 使用跨域资源共享的JSON注入:在请求另一个域的资源时,在请求中加上callback参数,并且服务器返回的数据是JSON格式,并用callback参数指定的函数名包裹返回的数据。

10. Js中的单线程和事件循环

  • Js是单线程,但是浏览器是多线程。
  • Js中采用了事件循环(Event Loop)来执行异步任务。
  • 所以,事件循环是一种异步编程模型,事件循环会不断地从任务队列(Task Queue)中取出待处理的任务并执行,直到任务队列为空为止。任务可以分为两类:宏任务(Macro Task)和微任务(Micro Task)。
  • 微任务会优先于宏任务执行

JS中是单线程的,意思是说JS在同一时间只能执行一段代码,不能同时执行多段代码。

但是JS是基于事件驱动的,它包含一个事件循环,这个事件循环可以让JS在执行代码的同时处理异步操作和事件。

当JS执行一段代码时,如果遇到异步操作(比如网络请求、定时器等),它会将这个操作放入事件队列中,然后继续执行下一段代码。当当前代码执行完毕后,JS会去事件队列中查看是否有待处理的事件,如果有,则立即执行这些事件对应的回调函数。

这样,JS就能在单线程的情况下实现异步操作和事件处理。事件循环的机制保证了JS能够高效地处理异步操作和事件,同时保持单线程的特性。

11. Vue2与Vue3中的双向数据绑定

在Vue2中,双向数据绑定是通过v-model指令实现的。v-model可以在表单元素上创建双向数据绑定,使输入的值与Vue实例中的数据属性相互影响,是指当数据发生变化时,Vue会自动更新视图中依赖此数据的部分,保持视图与数据的同步。Vue通过使用Object.defineProperty或者Proxy来追踪数据的变化,当数据被修改时,Vue会自动触发相关的视图更新。

而在Vue3中,双向数据绑定的实现方式有所改变。Vue3中引入了新的API,即使用 v-model 指令和 model 选项来创建双向数据绑定。v-model 指令用于在组件中创建双向数据绑定,而 model 选项用于在自定义组件中配置双向绑定的行为。

双向数据绑定就是:数据劫持 + 发布订阅模式(观察者模式)

在Vue中,响应式数据的观察者是Watcher对象,它会观察数据的变化并更新相关的视图。当响应式数据发生变化时,Watcher会接收到通知并执行更新视图的操作。接收者指的是视图中使用响应式数据的地方,它们会被Watcher更新以反映数据的变化。

总之,Vue的响应式数据通过观察者模式来实现,观察者负责监视数据的变化,接收者则是使用响应式数据的地方,它们会被观察者更新以反映数据的变化。

12. React Hook为什么不能放到条件语句中?

React Hook不能放到条件语句中的主要原因是,React Hook必须按照相同的顺序被调用,并且必须在函数的顶层作用域中调用。如果将React Hook放到条件语句中,它可能会在组件渲染过程中被跳过或者多次调用,导致组件状态的不一致性和不可预测行为。因此,React Hook只能被放在函数组件的最顶层作用域中调用,而不能放在循环、条件语句或嵌套函数中。这样能够确保React Hook在每次渲染时以相同的顺序被调用,从而保证组件的状态一致性和可预测性。

13. React有哪些常用的hooks?

  • useState:该 Hook 用于在函数组件中添加一个状态管理器。通过 useState,可以创建一个状态变量及其更新函数,并在组件内使用该变量来保存和更新组件的状态。
  • useEffect:该 Hook 用于在组件渲染完成后执行一些副作用操作(例如订阅数据、更新 DOM 等)。通过 useEffect,可以在组件加载、更新和卸载时设置和清理副作用操作,并且可以在副作用操作之间共享状态。
  • useContext:该 Hook 用于在组件之间共享一些全局的状态或函数,以避免通过多层嵌套的 Props 传递进行数据传输。通过 useContext,可以让组件在全局状态或函数的上下文中运行,并让它们能够方便地读取或更新全局状态或函数。
  • useReducer:该 Hook 用于在组件中使用一种“状态容器”模式,以避免通过多层 Props 传递或 Context 共享进行状态管理。通过 useReducer,可以创建一个状态容器及其更新函数,并在组件内使用该容器来保存和更新组件的状态。
  • useMemo:该 Hook 用于在组件渲染完成后缓存一些计算结果,以避免因为重复计算导致的性能问题。通过 useMemo,可以创建一个缓存变量,并在组件内使用该变量来保存计算结果并缓存。
  • useCallback:该 Hook 用于在组件渲染完成后,将一些函数进行缓存,以避免因函数重复创建导致的性能问题。通过 useCallback,可以创建一个缓存函数,并在组件内使用该函数来代替重复创建的函数。
  • useRef:该 Hook 用于在组件渲染完成后创建一个引用,以便在组件多次渲染时能够保留上一次渲染中的值。通过 useRef,可以创建一个引用变量,并在组件内使用该变量来保存一些持久化的数据。
  • useImperativeHandle:该 Hook 用于在组件中实现一些自定义的 Ref 对象,并且要求将一些组件内部的方法或状态暴露给父组件使用。通过 useImperativeHandle,可以创建一个自定义的 Ref 对象,并在组件内指定一些公开的方法或属性。
  • useLayoutEffect:该 Hook 与 useEffect 类似,但它会在浏览器渲染更新之前同步执行副作用操作,以确保 React 组件与浏览器同步更新。通常情况下,应该使用 useEffect,但在需要直接操作 DOM 元素或进行测量布局界面时,应当使用 useLayoutEffect。
  • useDebugValue:该 Hook 可以帮助开发者在调试工具中显示额外的信息,以便更好地理解 Hook 的使用和行为。通常情况下,这个 Hook 只用于调试过程中,而不是实际的应用程序代码中。

14. Promise 是什么?有什么用途?

14.1. 为什么要使用 Promise?

在了解 Promise 之前,先来看一下为什么需要它的出现。

JavaScript 是单线程非阻塞,异步的解释性脚本语言,异步操作(如文件操作、数据库操作、AJAX 请求、定时器等)是不可避免的。异步操作允许 JavaScript 在执行耗时任务时,不必阻塞主线程,而是可以继续执行其他代码,任务完成后再通知程序。

在 ES6 之前,通常使用回调函数(callback)来处理异步操作,但这种写法在处理多重嵌套时,会导致“回调地狱”(callback hell)现象,代码难以维护。比如下面的代码:

callback(() => {
  console.log("Hello!");
  callback(() => {
    console.log("Hello!");
    callback(() => {
      console.log("Hello!");
      callback(() => {
        console.log("Hello!");
      }, 200);
    }, 200);
  }, 200);
}, 200);

为了避免回调地狱,Promise 被引入来改善代码的可读性和可维护性。

14.2. 什么是 Promise?

Promise 是一种用于处理异步操作的对象,它代表一个尚未完成的操作,并允许在操作完成后处理成功或失败的结果。Promise 主要解决了异步编程中代码嵌套过深和错误处理困难的问题。

14.3. 如何使用 Promise?

Promise 是一个构造函数,可以通过 new 关键字来创建。它接受一个函数作为参数,这个函数被称为执行器(executor),并会立即执行。

new Promise((resolve, reject) => {
  console.log("executor 立即执行");
});

执行器函数有两个参数:resolverejectresolve 用于表示操作成功,reject 用于表示操作失败。比如:

function requestData(url) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (url === "example.com") {
        resolve("Success: Data fetched!");
      } else {
        reject("Error: Invalid URL");
      }
    }, 3000);
  });
}

// 请求成功
requestData("example.com").then((res) => {
  console.log(res); // Success: Data fetched!
});

// 请求失败
requestData("wrong-url.com").catch((error) => console.log(error)); // Error: Invalid URL

14.4. Promise 的三种状态

一个 Promise 对象有三种状态:

  1. pending:初始状态,表示操作尚未完成。
  2. fulfilled:操作成功,调用了 resolve
  3. rejected:操作失败,调用了 reject

14.5. 使用 .then() 处理异步结果

then() 方法用于注册回调函数,在 Promise 完成后执行。它接受两个参数:第一个是成功时的回调,第二个是失败时的回调。

requestData("example.com").then(
  (res) => {
    console.log(res);
  },
  (error) => {
    console.log(error);
  }
);

14.6. 链式调用

then() 可以链式调用,多个异步操作可以通过这种方式串联起来,避免回调地狱。例如:

requestData("example.com")
  .then((res) => {
    console.log(res);
    return 1;
  })
  .then((res) => {
    console.log(res); // 1
    return 2;
  })
  .then((res) => {
    console.log(res); // 2
  });

14.7. 错误处理

Promise 的另一个优点是可以统一处理错误。通过 .catch() 方法,可以捕获异步操作中的错误并处理。

fetch("https://example.com/data")
  .then((response) => response.json())
  .then((data) => {
    console.log(data);
  })
  .catch((error) => {
    console.error("Error:", error);
  });

14.8. finally() 方法

finally() 方法用于在 Promise 的状态无论是成功还是失败时,都要执行的代码。比如关闭加载动画等。

fetch("https://example.com/data")
  .then((response) => response.json())
  .then((data) => {
    console.log(data);
  })
  .catch((error) => {
    console.error("Error:", error);
  })
  .finally(() => {
    console.log("操作结束,关闭加载动画");
  });

14.9. 什么是 async/await?

async/await 是基于 Promise 的语法糖,使得异步代码看起来更像是同步代码。async 关键字标记的函数会返回一个 Promise,而 await 用于等待 Promise 的完成。

async function fetchData() {
  const res = await fetch("https://example.com/data");
  const data = await res.json();
  console.log(data);
}

fetchData();

通过 async/await,可以让异步代码更简洁,同时也更容易处理错误和调试。

14.10. 总结

  • Promise 是用于处理异步操作的对象,解决了回调地狱问题。
  • 它有三种状态:pendingfulfilledrejected
  • Promise 支持链式调用,可以通过 .then().catch().finally() 来处理异步结果和错误。
  • async/await 是 Promise 的语法糖,使异步代码更直观。

多个Promise并发
Promise.all
适用于同时对下文有依赖关系的多个请求。
会等待所有的 Promise 都会履行后返回结果,如果有一个 Promise 被拒绝,就立刻返回拒绝的错误。

const arr = [
  Promise.resolve(1),
  Promise.resolve(2),
  new Promise(resolve => {
    setTimeout(() => {
      resolve(3);
    }, 2000)
  })
];

console.time('1');
Promise.all(arr).then(res => {
  console.timeEnd('1'); // 2001 ms
  console.log('res', res); // [1, 2, 3]
});


Promise.any
有一个 Promise 被履行就返回结果,只有所有的 Promise 都被拒绝才返回失败。

const arr = [
  Promise.resolve(1),
  Promise.reject(2),
  Promise.reject(3),
];

Promise.any(arr).then(res => {
  console.log('res', res); // 1
}).catch(err => {
  console.log('err', err);
});


Promise.allSettled
返回的值都会处于履行状态,通过 status 和 value 去分别处理。

const arr = [
  Promise.resolve(1),
  Promise.reject(2),
  Promise.reject(3),
];

Promise.allSettled(arr).then(res => {
  console.log('res', res);
}).catch(err => {
  console.log('err', err);
});


 


Promise.race
永远取首先确定状态的 Promise 的值,履行就走 then,失败就走 catch。

const arr = [
  Promise.resolve(1),
  Promise.reject(2),
  new Promise(resolve => {
    setTimeout(() => {
      resolve(3);
    }, 2000)
  })
];

Promise.race(arr).then(res => {
  console.log('res', res); // 1
}).catch(err => {
  console.log('err', err);
});


一个比较有用的地方就是,race 可以用来终止耗时的操作

const promise1 = () => new Promise((resolve, reject) => {
  setTimeout(() => {
    reject('time out')
  }, 5000)
});

const promise2 = () => new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(1)
  }, 6000)
});

Promise.race([promise1(), promise2()]).then(res => {
  console.log('res', res);
}).catch(err => {
  console.log('err', err); // time out
});

15. 浏览器中的事件循环 (Event Loop)

15.1. 同步 (synchronous) 与异步 (asynchronous)

在讨论事件循环前,我们需要先了解同步与异步的概念。JavaScript 是单线程的编程语言,代码按照顺序一行一行执行,称为同步 (synchronous)。然而,这种执行方式可能带来问题。比如,如果一段代码需要等待外部数据(如从服务器获取数据),这可能会导致页面长时间无法响应,给用户带来很差的体验。因此,JavaScript 引入了异步 (asynchronous) 概念。

异步代码不会阻塞主线程,主线程可以继续执行其他操作,直到异步任务完成后再处理它。正是通过事件循环的机制,JavaScript 才能够解决单线程的局限性,使耗时操作不会阻塞主线程。

15.2. 事件循环 (Event loop) 的组成 - 执行栈和任务队列

事件循环本身并不存在于 JavaScript 内部,而是由 JavaScript 的执行环境(浏览器或 Node.js)实现的。它包括以下几个概念:

  • 堆 (Heap):用于存储对象的数据结构。
  • 栈 (Stack):后进先出(LIFO)数据结构。函数调用时会被推入栈顶,执行完后移出栈。
  • 队列 (Queue):先进先出(FIFO)数据结构。等待执行的任务会进入队列,等到栈空时再从队列取任务执行。
  • 事件循环 (Event loop):不断检查栈是否为空,若为空,则从队列取任务放入栈中执行。

事件循环的堆(Heap)、栈(Stack)和队列(Queue)

15.3. 事件循环 (Event loop) 的步骤

事件循环的执行过程可以总结为以下几步:

  1. 所有任务在主线程上执行,形成一个执行栈。
  2. 如果遇到异步任务(如 setTimeout),执行环境会调用相关 API 处理,完成后再将任务放入任务队列中。
  3. 一旦执行栈中的所有同步任务完成,事件循环会从任务队列中取出第一个任务放入栈中执行。
  4. 事件循环会持续这个过程,直到所有任务完成。

15.4. 宏任务 (Macro Task) 与微任务 (Micro Task)

JavaScript 的异步任务可以分为宏任务 (Macro Task) 和微任务 (Micro Task),它们的执行顺序不同。如果不区分这两类任务,代码的执行顺序可能会出乎意料。

例如,以下代码的输出顺序是什么?

console.log(1);
setTimeout(function () {
  console.log(2);
}, 0);
Promise.resolve()
  .then(function () {
    console.log(3);
  })
  .then(function () {
    console.log(4);
  });

如果仅考虑同步和异步,可能会认为输出顺序是 1234;但实际上正确答案是 1342。这是因为 Promise 任务属于微任务,而 setTimeout 属于宏任务。在一次事件循环中,宏任务只执行一个,之后会先执行微任务,因此 Promise 中的任务会先执行。

常见的宏任务和微任务如下:

  • 宏任务script(整体代码)、setTimeoutsetInterval、I/O、事件、postMessageMessageChannelsetImmediate (Node.js)。
  • 微任务Promise.thenMutationObserverprocess.nextTick (Node.js)。

执行顺序如下:

  1. 执行一次宏任务(最开始是整个 script,因此先执行 console.log(1))。
  2. 遇到宏任务时,放入宏任务队列。
  3. 遇到微任务时,放入微任务队列。
  4. 执行栈空时,先检查微任务队列,执行所有微任务。
  5. 执行浏览器渲染,接着开始下一个宏任务。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2170893.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

传输大咖49 | 科学研究院跨网文件交换高效、安全解决方案

在科学研究领域,数据的价值堪比黄金。科学研究所的日常运作依赖于大量的数据交换,高效的文件交换系统离不开内部合作和与外部合作伙伴的交流。然而,随着数据量的激增和网络环境的复杂性,传统的文件交换方法很难满足需求。本文将讨…

RK3568 android11 适配鼎桥MT5710-CN 5G模块

一,概述 鼎桥MT571X设备和Android系统主要通过USB接口进行数据通信,Android系统上的Linux内核需要根据鼎桥模块设备上报的USB设备接口加载USB驱动,USB驱动正确加载后,鼎桥模块才能正常工作。 Android系统中支持鼎桥模块设备相关的Linux内核驱动架构,如下图所示: 在Lin…

js删除emoji表情问题

emoji标签占位两个 &#xff0c;直接删除后一位会出现乱码符&#xff1b; 判断是否是emoji function isEmoji(char) {let code char.charCodeAt(0);return code>55296&&code<57343 } // 使用方法&#xff0c;传入单字符 console.log(isEmoji(1)); // false con…

Kubernetes 配置管理

一、什么是 ConfigMap&#xff1f; 在传统架构中&#xff0c;配置文件往往被保存在宿主机上&#xff0c;程序启动是可以指定某个配置文件&#xff0c;但是使用容器部署时&#xff0c;容器所在的节点并不固定&#xff0c;所以不能使用这种方式&#xff0c;此处在构建镜像时&…

【Redis】主从复制(下)--主从复制原理和流程

文章目录 主从复制原理主从节点建立复制流程图数据同步 psyncpsync的语法格式 psync运行流程全量复制全量复制的流程全量复制的缺陷有磁盘复制 vs 无磁盘复制 部分复制部分复制的流程复制积压缓冲区 实时复制 主从复制原理 主从节点建立复制流程图 保存主节点的信息从节点(sla…

感悟:糟糠之妻不下堂和现在女性觉醒的关系

古人说“糟糠之妻不下堂”真是害惨了中国女性&#xff0c;古代之所以有这一说法&#xff0c;大概是因为男子可以三妻四妾&#xff0c;妻子永远是正妻&#xff0c;也不需要讲究什么从一而终&#xff0c;更不会讲什么男德&#xff0c;只会要求女性学习女德、女训之类&#xff0c;…

性能测试:性能测试报告

性能测试报告是性能测试的产出物之一&#xff0c;它是对系统性能测试结果和数据的总结和分析&#xff0c;记录了系统在不同负载和场景下的性能表现和性能问题。性能测试报告提供了有关系统性能的详细信息&#xff0c;供项目团队、开发人员和其他相关利益相关者参考。 性能测试…

原生app云打包,更换图标,和名称。PDA的安装正式包

原生app云打包 复制下载即可&#xff0c;是正式版

Android下MVP和MVVM模式的实践

转载注明出处&#xff1a;https://blog.csdn.net/skysukai 1、前言 MVP和MVVM诞生已经好些年头了&#xff0c;记得刚毕业才参加工作的时候&#xff0c;第一次见到了有上万行的Activity&#xff0c;这种巨无霸的Activity维护起来简直就是噩梦。这时候&#xff0c;就需要进行代…

商标价值如何评估与增值?

商标是企业的标志&#xff0c;代表着企业的产品或服务质量、信誉和形象。一个具有高知名度和美誉度的商标&#xff0c;能够为企业带来巨大的商业价值。它不仅可以帮助企业在市场中脱颖而出&#xff0c;吸引消费者的关注和购买&#xff0c;还可以作为企业的重要资产进行融资、并…

无人便利店无人超市云值守收银系统源码

随着人力成本越来越高&#xff0c;很多门店越来想做无人值守模式&#xff0c;尤其是晚上休息时间等想让云值守客服来看店。自然要求收银系统需要可以在【有收银员值守】和【无收银员值守】两种模式灵活切换。 1. 有收银员值守模式 白天有收银员在店&#xff0c;收银员可以协助…

Tomcat服务与运用

案例准备 1.规划节点 IP 主机名 节点 192.168.20.20 tomcat Tomcat 2.基础准备 使用VMWare Workstation软件安装CentOS 7.2操作系统&#xff0c;镜像使用提供的CentOS-7-x86_64-DVD-1804.iso&#xff0c;最小化安装CentOS 7.2系统 案例实施 1.基础环境配置 1.1修改…

微信小程序的 button 标签的边框如何去除?

目录 问题描述&#xff1a; 问题原因&#xff1a; 解决办法&#xff1a; 方案一 方案二 问题描述&#xff1a; 实际开发中会发现这个 button 自带有样式&#xff0c;当背景颜色设置为白色的时候还有一个黑色的边框&#xff0c;刚开始那个边框怎么都去不掉 无法去除的边框…

IRR 之 24期免息等于免费?钱买保险还是余额宝?

一、IRR 是什么&#xff1f; 英文全称是 Internal Rate of Return 具体公式可以参考公众号 随园经济56&#xff5c;内部收益率 简单理解可以为&#xff1a; IRR是投资项目在整个生命周期中所能获得的平均年化收益率 更简单理解为&#xff0c;余额宝展现给你的年化收益 二、…

WLS2连接本地USB设备的方法

WLS2连接本地USB设备的方法 说明windows端1.下载usbipd-win并安装2.启动WSL3.以管理员身份运行Windows PowerShell”4.WSL中查看USB设备 说明 WLS2连接本地USB设备的方法 windows端 1.下载usbipd-win并安装 可下载**.msi文件&#xff0c;双击即可安装 2.启动WSL 3.以管理…

如何将Excel表格嵌入Web网页在线预览、编辑并保存到自己服务器上?

猿大师办公助手作为一款专业级的网页编辑Office方案&#xff0c;不仅可以把微软Office、金山WPS和永中Office的Word文档内嵌到浏览器网页中实现在线预览、编辑保存等操作&#xff0c;还可以把微软Office、金山WPS和永中Office的Excel表格实现网页中在线预览、编辑并保存到服务器…

如何在Windows、Mac和Linux系统上安装和更新Stable Diffusion WebUI

在图像生成领域&#xff0c;Stable Diffusion与Automatic1111表现出色&#xff0c;给MidJourney、OpenAI的DALL-E和Bing图像生成器带来了激烈的竞争。在本文中&#xff0c;我们将帮助您在本地安装Automatic1111 WebUI&#xff0c;以便您可以从文本提示创建出色的图像。 要生成…

原生代理IP是什么?

代理IP的各个类型称呼有很多&#xff0c;且它们在网络使用和隐私保护方面扮演着不同的角色。今天将探讨什么是原生IP以及原生IP和住宅IP之间的区别&#xff0c;帮助大家更好地理解这两者的概念和实际应用&#xff0c;并选择适合自己的IP类型。 一、什么是原生IP&#xff1f; 原…

智慧防灾,科技先行:EasyCVR平台助力地质灾害视频监测系统建设

随着科技的飞速发展&#xff0c;视频监控技术已成为地质灾害监测与预警的重要手段之一。在众多视频监控平台中&#xff0c;EasyCVR视频汇聚平台凭借其强大的视频整合、实时传输、视频处理及分发等能力&#xff0c;在地质灾害场景中展现出显著的应用优势。 一、实时监测与远程监…

2024年自动化、电气控制系统与设备国际学术会议(AECSE 2024)

在线投稿&#xff1a;学术会议-学术交流征稿-学术会议在线-艾思科蓝 2024年自动化、电气控制系统与设备国际学术会议&#xff08;AECSE 2024&#xff09;是致力于将“自动化与电气”领域的专家学者、研发者和技术人员汇集一堂的国际盛会。会议将于2024年10月18-20日在中国南京…