请说说你对 Promise 的理解
Promise 作为 JS 的重点知识,也是面试官最爱问的问题之一。
当对方提出一个问题的时候,你通常需要考虑3个问题:
- 什么用?【产生工具的本质就是为了更好的解决某类问题】
- 是什么?【知道工具是由什么造的,有什么特性,这样我们才能更好的去使用工具】
- 怎么用?【上手!】
一、什么用?(Promise 发明出来是干啥的)
Promise 是目前 JS 中最好的异步处理方案,很好的解决了回调地狱的问题。
在 ES6 出来之前,我们想解决异步问题就要使用回调函数,当回调函数用的多了,代码结构就会嵌套的很深,这样就形成了回调地狱。这样的代码结构阅读性差,并且难以维护。
// 回调地狱
setTimeout(() => {
// 发送请求获取数据
setTimeout(() => {
// 此层数据需要依赖上层函数的数据
setTimeout(() => {
// 此层数据需要依赖上层函数的数据
// 更深的回调......
}, 0)
}, 0)
}, 0)
二、是什么?(Promise 是什么成分)
Promise 本质是一个构造函数,我们可以通过 new 关键字去实例化一个 promise 对象
const promise = new Promise(() => {}) // 需要传入一个函数做参数
Promise 既然是构造函数,那它身上肯定有原型和一些属性、方法。
2.1 Promise 有6个静态方法
- Promise.resolve(value)
- 用于返回一个
fulfilled
状态的 Promise
- 用于返回一个
- Promise.reject(reason)
- 用于返回一个
rejected
状态的 Promise
- 用于返回一个
- Promise.all(iterable))
- 参数 iterable 是一个可被迭代的对象,例如 Array、Set、Map 等等。该对象里包含多个 Promise 对象
- 当 iterable 里的所有 Promise 对象都返回成功的结果,则会返回一个 Array,里面包含所有成功的结果
- 若 iterable 里的一个 Promise 对象返回了失败的原因,则会返回该原因
- Promise.allSettled(iterable)
- 当 iterable 里的所有 Promise 对象都敲定状态时,无论成功或失败,都会返回一个数组,里面包含所有结果
- Promise.any(iterable)
- 当 iterable 里的一个 Promise 对象返回成功的结果时,则会返回该 Promise 的结果
- 当 iterable 里所有的 Promise 对象都返回失败的原因,则会返回一个失败的 Promise
- Promise.race(iterable)
- 当 iterable 里的一个 Promise 对象最先敲定状态,无论成功或失败,都会返回该 Promise 的结果
2.2 Promise 有3个实例方法
-
Promise.prototype.then()
-
Promise.prototype.catch()
-
Promise.prototype.finally()
三、怎么用?(如何去使用 Promise)
首先我们需要知道 Promise 有3种状态:pending
等待,fulfilled
满足,rejected
拒绝。
起初 Promise 是 pending
的状态,当状态敲定的时候,它会进入 fulfilled
或 rejected
,并且这个操作是不可逆的。
// 创建一个 promise 实例对象
// ** Promise 需要一个函数作为参数,并且该函数需要传入两个参数 resolve 和 reject
// ** resolve 和 reject 其实就是 Promise 的两个静态方法,我们需要这两个方法来告诉 Promise 成功的结果或失败的原因
const promise = new Promise((resolve, reject) => {
// 使用该 isTrue 来模拟判断数据是否请求成功
let isTrue = true
// 若数据请求成功
if (isTrue) {
// 使用 resolve 返回成功的结果
resolve('成功的数据')
}
// 若数据请求失败
else {
// 使用 reject 返回失败的原因
reject('失败的原因')
}
})
promise 实例创建完了,那我们怎么处理成功的结果或失败的原因呢?使用 then()
!
// 使用 then() 处理成功的结果或失败的原因
// ** then() 就是 Promise 原型上的方法,可以接收两个函数作为参数
// ** 第一个函数,可以接收到成功的结果
// ** 第二个函数,可以接收到失败的原因
promise.then(value => {
// 处理成功的结果
console.log(value)
}, reason => {
// 处理失败的原因
console.log(reason)
})
或者使用 catch()
统一处理失败的原因。
// 使用 catch() 捕获失败的原因
// ** 因为 then() 方法返回的依然是一个 Promise 实例,所以可以链式调用
// ** 当我们需要多次使用 then() 处理结果时,我们可以省略 then() 的第二个参数,使用 catch() 统一捕获异常状态
promise.then(value => {
// 处理成功的结果
// ** 即便不写 return, then() 返回的依旧是一个 Promise 对象,并且是 fulfilled 状态的 Promise 对象
return Promise.resolve(value)
}).then(value => {
// 处理成功的结果
console.log(value)
}).catch(error => {
// 捕获异常状态
console.log(error)
})
使用 finally()
做善后工作。
// 无论成功还是失败,在 promise 结束时都可以执行 finally() 来处理一些善后的工作
// ** 可以避免同样的操作在 then() 和 catch() 各执行一次
promise.then(value => {
// 处理成功的结果
console.log(value)
}).catch(error => {
// 捕获异常状态
console.log(error)
}).finally(() => {
// 善后工作
console.log('为了部落,永不加班!!!')
})