卓望数码前端一面
原文网址:https://www.nowcoder.com/discuss/409361218459234304?sourceSSR=search
1.css中flex布局有哪些常见的属性
display:flex
首先让一个容器为flex布局应该写 display:flex
flex-direction
flex有两个关键的轴,分别是主轴和交叉轴,可以通过flex-direction来设置主轴的方向,默认值为flex-direction:row
可选值flex-direction: row | row-reverse | column | column-reverse;
flex-wrap
flex布局默认显示在一行上面,如果flex的项目宽度大于flex容器的话默认不会换行,flex项目会被压缩然后挤在一行显示 flex-wrap:wrap | nowrap
justify-content
控制在主轴方向上的对齐方式,默认值为flex-start
justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly;
align-item
控制元素在交叉轴方向上的对齐方式,默认值为stretch(拉伸)
align-items: flex-start | flex-end | center | baseline | stretch;
align-content:
align-content: flex-start | flex-end | center | space-between | space-around | stretch;
控制多行在交叉轴方向上的对齐方式,类似于justify-content
order
设置顺序
flex:整数
设置item项目所占的大小
align-self
子元素可以设置align-self控制自己在交叉轴方向上对齐方式
.flex {
display: flex;
align-items: flex-start;
}
.flex3 {
align-self: flex-end;
}
在水平方向上控制子元素对齐并没有justify-self
属性,而是使用margin
属性,通过把左或右边距设置为auto
来控制水平对齐,比如把 flex3
放到最右边:
.flex3 {
margin-left: auto;
}
2.js有哪些基础类型
- 数字(Number):用于表示数值。例如:42、3.14等。
- 字符串(String):用于表示文本数据。例如:"Hello, World!"等。
- 布尔值(Boolean):用于表示逻辑值,只有两个可能的值:true(真)和false(假)。
- null:表示一个空值或不存在的对象。
- undefined:表示未定义的值,通常用于声明了变量但未给其赋值时的默认值。
- Symbol:在ES6引入的一种新类型,表示独一无二的值,用于创建唯一的对象属性名。
还有一种特殊的基础类型:BigInt,在处理超过JavaScript Number类型范围的大整数时使用
如何判断数据的类型
思路:
但是 instanceof
运算符一定要是判断对象实例的时候才是正确的,也就是说,它不能判断原始类型,如下代码所示:
const str1 = "qwe";
const str2 = new String("qwe");
console.log(str1 instanceof String); // false,无法判断原始类型。
console.log(str2 instanceof String); // true
1.首先使用typeof判断数据的类型,如果不是object,那么就可以直接返回.
- 无法判断
null
。 - 无法判断除了
function
之外的引用类型。
2.如果说是object,那就需要另外的判断,使用Object.prototype.toString.call(target)
调用 Object.prototype.toString
方法,会统一返回格式为 [object Xxx]
的字符串,需要注意的是,在调用该方法时,需要加上 call
方法,如果不改变 this
指向为我们的目标变量 xxx
,this
将永远指向调用的 Object.prototype
,也就是原型对象,对原型对象调用 toString
方法,结果永远都是 [object Object]
,
function getType(target) {
const type = typeof target;
if (type !== "object") {
return type;
}
return Object.prototype.toString
.call(target)
.slice(8,-1)
}
3.基础类型和引用类型的区别是什么
基本数据类型:
- 字符串(String)
- 数字(Number)
- 布尔值(Boolean)
- 空值(Null)
- 未定义(Undefined)
- 符号(Symbol)(ES6新增)
引用数据类型:
- 对象(Object)
- 数组(Array)
- 函数(Function)
- 正则表达式(RegExp)
- 等等…
下面是基本类型和引用类型的区别:
- 存储方式:基本类型的值直接存储在变量所分配的内存空间中,而引用类型的值存储在堆内存中,并通过引用(内存地址)来访问。
- 复制方式:当将一个基本类型的值赋给另一个变量时,会创建一个新值的副本,这两个变量是完全独立的,互不影响。而当将一个引用类型的值赋给另一个变量时,实际上是将引用复制给了新变量,它们引用同一个对象,因此改变其中一个变量会影响另一个。
- 比较方式:基本类型的值比较的是它们的实际值,如果值相等,则认为相等。而引用类型的比较是比较它们的引用地址,只有当两个变量引用同一个对象时才会认为相等。
- 可变性:基本类型的值是不可变的,一旦创建就不能被修改,只能创建新的值。而引用类型的值是可变的,可以添加、删除、修改对象的属性和方法。
vue有哪些生命周期
主要有8个生命周期钩子,然后路由有两个生命周期钩子,所以一共有10个生命周期钩子函数
- beforeCreate:在实例被创建之前调用。此时组件的数据观察和事件机制尚未初始化。
- created:在实例创建完成后调用。在这个阶段,可以访问组件的数据和方法。
- beforeMount:在组件挂载到 DOM 之前调用。此时,模板编译完成但尚未将组件插入到 DOM 中。
- mounted:在组件挂载到 DOM 后调用。此时,组件已经被插入到 DOM 中,可以进行 DOM 操作。
- beforeUpdate:在数据更新之前调用,发生在虚拟 DOM 重新渲染和打补丁之前。可以在这里进行状态更新之前的准备工作。
- updated:在数据更新之后调用。组件的更新已经完成,可以执行依赖于 DOM 的操作。
- beforeDestroy:在实例销毁之前调用。可以在这里进行清理操作,例如取消定时器、取消订阅等。
- destroyed:在实例销毁后调用。此时,组件已经被销毁,所有的事件监听器和子组件也都被移除。
- activated/deactivated,在使用路由的时候配合keep-alive缓存组件,activated在进入路由缓存组件的时候会被调用,deactivated在离开路由缓存组件的时候会调用。
vue数据请求一般放在哪些生命周期钩子里,这些钩子之间有什么区别
created
是在组件实例一旦创建完成的时候立刻调用,这时候页面dom
节点并未生成;mounted
是在页面dom
节点渲染完毕之后就立刻执行的。触发时机上created
是比mounted
要更早的,两者的相同点:都能拿到实例对象的属性和方法。 讨论这个问题本质就是触发的时机,放在mounted
中的请求有可能导致页面闪动(因为此时页面dom
结构已经生成),但如果在页面加载前完成请求,则不会出现此情况。建议对页面内容的改动放在created
生命周期当中。
- beforeCreate 和 created:在
beforeCreate
钩子中,组件的数据观察和事件机制尚未初始化,因此不适合进行数据请求。而在created
钩子中,组件的实例已经创建完成,可以进行数据请求和对数据进行操作。 - beforeMount 和 mounted:在
beforeMount
钩子中,模板已经编译完成,但尚未将组件插入到 DOM 中,因此在这个阶段不适合进行数据请求。而在mounted
钩子中,组件已经被挂载到 DOM 中,可以进行数据请求和操作 DOM 元素。 - beforeUpdate 和 updated:在
beforeUpdate
钩子中,数据更新之前被调用,这个阶段通常用于准备数据更新前的操作,而不是进行新的数据请求。在updated
钩子中,组件的数据已经更新完成,并且 DOM 也已经重新渲染,此时可以执行依赖于 DOM 的操作。
讲述一下vue的父组件和子组件的生命周期执行顺序
- 父组件beforeCreate:父组件实例被创建之前执行。
- 父组件created:父组件实例被创建之后执行,此时父组件的数据观测和事件配置已完成,但尚未挂载到DOM上。
- 父组件beforeMount:父组件挂载之前执行,此时模板编译已完成,但尚未将编译得到的DOM挂载到页面上。
- 子组件beforeCreate:子组件实例被创建之前执行。
- 子组件created:子组件实例被创建之后执行,此时子组件的数据观测和事件配置已完成,但尚未挂载到DOM上。
- 子组件beforeMount:子组件挂载之前执行,此时模板编译已完成,但尚未将编译得到的DOM挂载到页面上。
- 子组件mounted:子组件挂载完成后执行,此时子组件的DOM已经挂载到页面上,可以进行DOM操作。
- 父组件mounted:父组件挂载完成后执行,此时父组件的DOM已经挂载到页面上,可以进行DOM操作。
- 父组件beforeUpdate:父组件更新之前执行,此时数据发生改变,但尚未更新DOM。
- 子组件beforeUpdate:子组件更新之前执行,此时数据发生改变,但尚未更新DOM。
- 子组件updated:子组件更新完成后执行,此时子组件的DOM已经更新完毕。
- 父组件updated:父组件更新完成后执行,此时父组件的DOM已经更新完毕。
- 父组件beforeUnmount:父组件卸载之前执行,此时父组件即将被销毁。
- 子组件beforeUnmount:子组件卸载之前执行,此时子组件即将被销毁。
- 子组件unmounted:子组件卸载完成后执行,此时子组件已经被销毁,DOM也已经从页面上移除。
- 父组件unmounted:父组件卸载完成后执行,此时父组件已经被销毁,DOM也已经从页面上移除。
vue-router的路由守卫有哪些
路由守卫
作用:对路由权限进行控制
分类
全局路由守卫
独享路由守卫
组件内路由守卫
用户鉴权有那些方案
Cookie + Session
通过登录接口,把账号密码发送给服务器,,服务器校验通过之后会生成session对象存储在内存中,然后把set-cookie通过响应头发送给客户端,客户端拿到cookie后会保存起来,当访问其它业务接口的时候会把对应网站的cookie发送过去,服务器通过sessionid,就会找到对应的session对象继续会话、返回数据、展示页面。
缺点:
session会存储在服务器的内存里面,随着用户访问的越来越多,占用的内存也就越来越多,服务器的压力也就越大,当然也可以把session进行持久化,但是这样也会带来额外的开销。其次,当用户在一台服务器访问验证登录之后,但是用户是不能访问其它服务器的因为其它服务器没有这个session对象。
JWT
什么是jwt:
JSON Web Token 经加密的包含用户信息且具有时效性的固定格式字符串
组成:
header.payload.signature
header:主要存储加密算法,数据类型等原数据
payload:主要存储自定义的非敏感信息
signature:signature是怎么来的呢?通过对header和payload进行Base64编码,得到编码后的字符串,注意这里是编码,不是加密。然后把两者进行拼接,最后通过header声明的算法和在服务器里面的密钥一起加密得到signature得到,然后就把这些合成一个完整的token返回给客户端。
过程:
用户通过调用登录接口发送账号密码给服务器,服务器校验通过之后生成token返回给客户端,然后客户端把token保存起来,当访问其它业务接口时,通常会把token放在header里面然后发送给服务器,服务器校验收到的token,如果合法,就返回数据等等之类的操作。
服务器如何校验收到的token:
token有固定的格式,所以可以直接从用户发过来的token获得header、payload。因为header和payload时通过base64编码得到的,所以同样可以解密得到里面的加密方式。
然后使用header和payload以及保存在服务器端的密钥通过header指定的加密算法得到计算后的签名。如果一致就合法,反之不合法。
jwt就是使用时间换空间,消耗了cpu的算力但是节省了空间。
- 无法撤销令牌:一旦JWT令牌签发,无法撤销或失效,除非令牌过期。这是因为JWT令牌是无状态的,服务端无需维护令牌的状态信息。如果需要撤销某个特定的令牌,就需要引入一些额外的机制来管理令牌的撤销。
- 令牌过期问题:JWT中的令牌具有一定的有效期限,一旦过期,客户端必须重新获取新的令牌。这可能会导致一些问题,例如用户在使用应用期间令牌过期,需要重新进行身份验证,这可能会对用户体验产生负面影响。
- 令牌大小增加:JWT令牌包含了一些元数据和签名信息,这使得令牌的大小相对较大。在每次请求中传输较大的令牌可能会增加网络流量和延迟,特别是在移动网络环境下。
- 令牌安全性依赖密钥管理:JWT使用密钥进行签名和验证,这意味着令牌的安全性高度依赖密钥的管理和保护。如果密钥泄露或被攻击者获取,攻击者可以篡改令牌或伪造有效的令牌。
Oauth2.0(Open Authorization)
例子:
用户要登录 百度 可以使用微信登录
一个关于授权的开放网络标准
允许用户授权第三方应用访问存储在其它服务提供者上的信息
不需要将用户名和密码提供给第三方应用(这里的应用指的是刚刚的百度,服务提供者是微信)
授权码模式:
1.用户在应用程序中,应用程序尝试获取用户保存在资源服务器上的信息,比如用户的身份信息和头像,应用程序首先让重定向用户到授权服务器,告知申请资源的读权限,并提供自己的client id。
2.到授权服务器,用户输入用户名和密码,服务器对其认证成功后,提示用户即将要颁发一个读权限给应用程序,在用户确认后,授权服务器颁发一个授权码(authorization code)并重定向用户回到应用程序。
3.应用程序获取到授权码之后,使用这个授权码和自己的client id/secret向授权服务器申请访问令牌/刷新令牌(access token/refresh token)。授权服务器对这些信息进行校验,如果一切OK,则颁发给应用程序访问令牌/刷新令牌。
4.应用程序在拿到访问令牌之后,向资源服务器申请用户的资源信息
5.资源服务器在获取到访问令牌后,对令牌进行解析(如果令牌已加密,则需要进行使用相应算法进行解密)并校验,并向授权服务器校验其合法性,如果一起OK,则返回应用程序所需要的资源信息。
可以看到,在整个过程中应用程序没有接触到用户的密码。
- 简化模式(Implicit grant type)
有些 Web 应用是纯前端应用,没有后端。这时就不能用上面的方式了,必须将令牌储存在前端。RFC 6749 就规定了第二种方式,允许直接向前端颁发令牌。这种方式没有授权码这个中间步骤 - 密码模式(Resource Owner Password Credentials Grant)
如果你高度信任某个应用,RFC 6749 也允许用户把用户名和密码,直接告诉该应用。该应用就使用你的密码,申请令牌 - 客户端模式(Client Credentials Grant)
适用于没有前端的命令行应用,即在命令行下请求令牌
单点登录
认证中心:
认证中心就是一个负责处理登录请求的web服务,用户统一在认证中心登录后,认证中心记录用户的登录状态,并将token写入cookie,此时这个cookie是认证中心的,应用系统是访问不到的。
应用系统检查当前有没有token,如果没有,就说明用户在当前系统中没有登录,就跳转到认证中心。然后进行登录,登录成功之后会生成一个token,回传到应用系统,应用系统拿着token再去认证中心认证,防止用户伪造。
确认无误之后就可以返回信息了
cookie、session、token区别
Cookie、Session、Token 是在 Web 应用程序中用于管理用户身份验证和状态的常见机制。它们在功能和用途上有所不同,下面是它们的区别:
- Cookie(HTTP Cookie): Cookie 是一种在客户端(通常是浏览器)存储数据的机制。当用户访问网站时,服务器可以在响应中通过 Set-Cookie 标头将一个小段数据发送给客户端,并在之后的请求中通过 Cookie 标头将该数据发送回服务器。这些数据通常用于跟踪用户会话、实现个性化设置和记住用户偏好。
Cookie 的特点包括:
- 存储在客户端,以文本文件的形式存在。
- 可以设置过期时间,可以是会话级别的(浏览器关闭后自动删除)或持久性的(在一段时间后过期)。
- 每次请求都会将 Cookie 发送到服务器,增加了网络开销。
- 存储容量有限,每个域名的 Cookie 数量和总大小都有限制。
Session: Session 是一种在服务器端存储数据的机制。当用户第一次访问网站时,服务器会为该用户创建一个唯一的会话标识符(session ID)。该标识符通常通过 Cookie 或 URL 参数发送给客户端,并在之后的请求中通过 Cookie 或参数将会话标识符发送回服务器。
Session 的特点包括:
- 存储在服务器端,通常以哈希表或数据库中的形式保存。
- 可以存储较大量的数据,不受客户端限制。
- 会话数据在服务器端进行管理,可以存储敏感信息。
- 会话 ID 可以是临时的(在浏览器关闭后删除)或持久性的(在一段时间后过期)。
- 需要服务器进行状态管理,可能增加服务器负担。
Token: Token 是一种轻量级的身份验证和授权机制,常用于前后端分离的应用程序和 API。当用户成功登录时,服务器会生成一个包含用户身份信息和其他相关数据的令牌(token),然后将其发送给客户端。客户端在后续请求中通常会将该令牌包含在请求头中或通过其他方式发送给服务器进行验证。
Token 的特点包括:
- 通常是加密的,以防止被篡改。
- 存储在客户端,通常以本地存储或会话存储的形式存在。
- 不依赖于服务器端的状态管理,可以在分布式环境中使用。
- 令牌可以有不同的过期策略,如短期访问令牌和长期刷新令牌。
Cookie,localstorage和sessionstorage有什么区别
Cookie、LocalStorage和SessionStorage是在Web应用程序中用于在客户端存储数据的机制,它们之间有以下区别:
1.Cookie:
- 存储容量:Cookie 的存储容量较小,通常限制为几KB。
- 数据发送:每次请求都会将Cookie自动发送到服务器,包括在请求头中。
- 过期时间:可以设置Cookie的过期时间,可以是会话级别的(浏览器关闭后自动删除)或持久性的(在一段时间后过期)。
- 功能:Cookie通常用于跟踪用户会话、实现个性化设置和记住用户偏好。
2.LocalStorage:
- 存储容量:LocalStorage 的存储容量较大,通常限制为几十MB。
- 数据发送:LocalStorage 的数据不会自动发送到服务器,仅在客户端使用。
- 生命周期:LocalStorage 的数据会一直保留,除非被主动清除或通过代码删除。
- 功能:LocalStorage 用于在浏览器中持久地存储数据,以供后续使用,如保存用户首选项、本地缓存等。
3.SessionStorage:
- 存储容量:SessionStorage 的存储容量与LocalStorage相同,较大,通常限制为几十MB。
- 数据发送:SessionStorage 的数据不会自动发送到服务器,仅在客户端使用。
- 生命周期:SessionStorage 的数据在用户关闭浏览器窗口后会被自动删除。
- 功能:SessionStorage 用于在浏览器中存储特定会话期间的数据,一旦会话结束,数据将被清除。
总结: Cookie 适用于在服务器和客户端之间传递数据、跟踪用户状态等;LocalStorage 用于在浏览器中长期保存数据,不受会话限制;SessionStorage 用于在浏览器中临时保存数据,仅在当前会话有效。
Cookie如何设置过期时间
在设置 Cookie 的时候,你可以通过设置 Expires 或 Max-Age 属性来指定 Cookie 的过期时间。这些属性告诉浏览器何时删除 Cookie。以下是设置过期时间的方法:
设置过期时间(Expires 属性):
Set-Cookie: cookieName=value; Expires=Sat, 03 Jun 2023 23:59:59 GMT;
在上面的示例中,将 Expires
属性设置为具体的日期和时间,表示该 Cookie 将在指定的日期和时间过期。当浏览器检测到 Cookie 已经过期时,会自动将其删除。
设置过期时间(Max-Age 属性):
Set-Cookie: cookieName=value; Max-Age=3600;
在上面的示例中,Max-Age
属性设置为一个以秒为单位的数值。该数值表示 Cookie 将在创建后的指定秒数后过期。例如,上面的示例将使 Cookie 在创建后的一个小时(3600 秒)后过期。
需要注意的是,如果同时设置了 Expires 和 Max-Age 属性,Max-Age 属性的优先级更高,即浏览器将依据 Max-Age 属性的值来确定 Cookie 的过期时间。
如果不设置过期时间,默认情况下,Cookie 是会话级别的,即当用户关闭浏览器时,Cookie 将被删除。
Localstorage如何设置过期时间
LocalStorage 是一个持久性的存储机制,它的数据会一直保留在浏览器中,不会自动过期。LocalStorage 不提供直接的方法来设置数据的过期时间,因此需要自己在数据中存储过期时间,并在读取数据时进行判断。
1.设置数据及过期时间:
// 设置数据及过期时间为1小时后
var data = {
value: 'example',
expires: new Date().getTime() + 3600 * 1000 // 当前时间 + 1小时的毫秒数
};
localStorage.setItem('data', JSON.stringify(data));
2.读取数据并检查过期时间:
var storedData = localStorage.getItem('data');
if (storedData) {
var data = JSON.parse(storedData);
if (data.expires && new Date().getTime() > data.expires) {
// 数据已过期,执行相应操作,如删除数据等
localStorage.removeItem('data');
} else {
// 数据未过期,可以使用
var value = data.value;
// 其他操作...
}
}
介绍一下es6的promise语法
ES6 引入了 Promise 对象,用于更方便地处理异步操作。Promise 提供了一种更具可读性和可维护性的方式来组织和处理异步代码。下面是 Promise 的基本语法和用法:
- 创建 Promise 对象: Promise 对象是通过实例化 Promise 类来创建的,构造函数接受一个函数作为参数,该函数被称为执行器(executor)。执行器函数会立即执行,并接收两个参数:resolve(成功时的回调函数)和 reject(失败时的回调函数)。
javascriptCopy codeconst promise = new Promise((resolve, reject) => {
// 异步操作的代码
});
- 处理 Promise 对象的状态: Promise 对象有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。一旦状态变为 fulfilled 或 rejected,Promise 对象的状态就凝固了,无法再次改变。
- 当异步操作成功时,调用
resolve(value)
将 Promise 状态改为 fulfilled,并将结果传递给后续处理程序。 - 当异步操作失败时,调用
reject(reason)
将 Promise 状态改为 rejected,并将错误原因传递给后续处理程序。
- 处理 Promise 对象的结果: 可以使用
then()
方法来处理 Promise 对象的结果。then()
方法接收两个参数:onFulfilled
(可选,处理成功的回调函数)和onRejected
(可选,处理失败的回调函数)。
promise.then(
(value) => {
// 处理成功的回调函数
},
(reason) => {
// 处理失败的回调函数
}
);
- Promise 链式调用: 通过返回新的 Promise 对象,可以实现 Promise 链式调用。在
then()
方法的回调函数中,可以返回一个新的 Promise 对象。
promise.then((value) => {
// 处理成功的回调函数
return anotherAsyncOperation(value); // 返回新的 Promise 对象
}).then((result) => {
// 处理新的 Promise 对象的结果
}).catch((error) => {
// 处理任何一个 Promise 中的错误
});
在链式调用中,每个 then()
方法都可以返回一个新的 Promise 对象,使得多个异步操作能够按照顺序执行,并且可以通过 catch()
方法统一捕获错误。
这是 Promise 的基本语法和用法,它提供了一种更优雅和可读性更好的方式来处理异步操作。通过 Promise,可以避免回调地狱(callback hell)和层层嵌套的回调函数,提升代码的可维护性和可扩展性。
promise有哪些常用api,这些api效果是什么
Promise 提供了一些常用的 API 来处理异步操作,以下是其中几个常用的 API 和它们的效果:
then(onFulfilled, onRejected)
:
then()
方法用于处理 Promise 对象的成功和失败状态,并返回一个新的 Promise 对象。它接收两个参数,onFulfilled
和 onRejected
,分别表示处理成功和失败的回调函数。返回的 Promise 对象将根据回调函数的执行结果决定其状态。
-
如果 Promise 对象处于 fulfilled 状态,将调用
onFulfilled
并将 Promise 的值作为参数传递给它。 -
如果 Promise 对象处于 rejected 状态,将调用
onRejected
并将 Promise 的错误原因作为参数传递给它。 -
如果省略了
onFulfilled
或onRejected
,则将使用默认的穿透(pass-through)行为,将值或错误原因传递给下一个then()
的回调函数。
catch(onRejected)
:
catch()
方法用于处理 Promise 对象的失败状态,相当于 then(null, onRejected)
。它接收一个参数 onRejected
,表示处理失败的回调函数。如果 Promise 对象处于 rejected 状态,则调用 onRejected
并将错误原因作为参数传递给它。
finally(onFinally)
:
finally()
方法用于在 Promise 对象的状态无论是成功还是失败时,都执行特定的操作。它接收一个参数 onFinally
,表示在 Promise 结束时要执行的回调函数,无论其状态是 fulfilled 还是 rejected。
- 如果 Promise 对象处于 fulfilled 状态,则调用
onFinally
并传递该状态的值作为参数。 - 如果 Promise 对象处于 rejected 状态,则调用
onFinally
并传递错误原因作为参数。 finally()
方法返回一个新的 Promise 对象,该对象在onFinally
执行完成后将采用原始 Promise 对象的状态和值。
Promise.all(iterable)
: Promise.all()
方法接收一个可迭代对象(比如数组)作为参数,返回一个 Promise 对象,该对象在所有输入 Promise 对象都成功时才会成功,否则会失败。
-
如果所有输入的 Promise 对象都成功解决,则返回的 Promise 对象的状态为 fulfilled,并将一个包含所有 Promise 结果值的数组作为结果值。
-
如果输入的任何一个 Promise 对象失败(被拒绝),则返回的 Promise 对象的状态为 rejected,并将第一个失败 Promise 的错误原因作为结果。
Promise.race(iterable)
: Promise.race()
方法接收一个可迭代对象作为参数,返回一个 Promise 对象,该对象在任何一个输入 Promise 对象解决(无论成功或失败)时就会解决。
- 如果任何一个输入的 Promise 对象解决为 fulfilled,则返回的 Promise 对象的状态为 fulfilled,并将第一个解决的 Promise 的值作为结果值。
- 如果任何一个输入的 Promise 对象解决为 rejected,则返回的 Promise 对象的状态为 rejected