Promise

2022/9/14

# 概念

从语法上,Promise 是一个构造函数,接收一个函数作为参数,该函数有两个参数 resolve 和 reject。

new Promise(function(resolve, reject) {

})

从功能上,promise 对象用来封装一个异步操作并且可以获取其成功/失败的结果值

# 2 个属性

1) state:表示primose当前的状态,值为 pending(进行中)、fullfilled(完成)、rejected(失败)
2) result:结果

调用 resolve() 可使 pending 变为 fullfilled,调用 reject() 或报错会使 pending 变为 rejected。promise 的状态一旦改变之后就固定了,不会再变

# 方法

1. Promise 构造函数: Promise (excutor) {}
(1) executor 函数: 执行器 (resolve, reject) => {}
(2) resolve 函数: 内部定义成功时我们调用的函数 value => {}
(3) reject 函数: 内部定义失败时我们调用的函数 reason => {}
说明: executor 会在 Promise 内部立即同步调用,异步操作在执行器中执行

let p = new Promise((resolve, reject) => {

})

2. Promise.prototype.then 方法: (onResolved, onRejected) => {}
(1) onResolved 函数: 成功的回调函数 (value) => {}
(2) onRejected 函数: 失败的回调函数 (reason) => {}
说明: 指定用于得到成功 value 的成功回调和用于得到失败 reason 的失败回调

返回值: 一个新的 promise 对象,具体如下:
① 如果抛出异常, 新 promise 变为 rejected, reason 为抛出的异常
② 如果返回的是非 promise 的任意值, 新 promise 变为 resolved, value 为返回的值
③ 如果返回的是另一个新 promise, 此 promise 的结果就会成为新 promise 的结果

let p = new Promise((resolve, reject) => {
    setTimeout(()=>{
      resolve(111)
    }, 1000)
  })

  p.then(value => console.log('one ->' + value), reason => {})
  p.then(value => console.log('two ->' + value))
  p.then(value => console.log('three ->' + value))

  // 3个都会输出,说明可以为一个 promise 指定多个回调,且当promise 变为对应状态时,相对应的所有回调函数都会执行

3. Promise.prototype.catch 方法: (onRejected) => {}
(1) onRejected 函数: 失败的回调函数 (reason) => {}
说明: then()的语法糖, 相当于: then(undefined, onRejected)

4. Promise.resolve 方法: (value) => {}
(1) value: 成功的数据或 promise 对象
说明: 返回一个成功/失败的 promise 对象

5. Promise.reject 方法: (reason) => {}
(1) reason: 失败的原因
说明: 返回一个失败的 promise 对象

6. Promise.all 方法: (promises) => {}
(1) promises: 包含 n 个 promise 的数组
说明: 返回一个新的 promise, 只有所有的 promise 都成功才成功, 只要有一个失败了就直接失败

let sign = 0

let p1 = new Promise((resolve, reject) => {
  sign ++
  resolve(111)
})
let p2 = new Promise((resolve, reject) => {
  sign ++
  reject(22)
})
let p3 = new Promise((resolve, reject) => {
  
  reject(33)
  sign ++
})
let p4 = new Promise((resolve, reject) => {
  
  reject(44)
  sign ++
})

let res = Promise.all([p1, p2, p3, p4])
// 返回一个新的 promise,只有当所有 promise 都成功时才成功,此时 result 为一个数组,包含所有 promise 的返回值
// 只要有一个失败的 promise,返回的 promise 的状态就是失败,此时 result 为第一个失败的 promise 的值 

console.log(res) // 一个 promise 对象,状态为 rejected,结果为 22
console.log(sign) // 4,表明所有的promise都会执行,而不是遇到失败即返回

7. Promise.race 方法: (promises) => {}
(1) promises: 包含 n 个 promise 的数组
说明: 与 Promise.all() 类似,返回一个新的 promise, 但第一个完成的 promise 的结果状态就是最终的结果状态

# Promise 优缺点

# 优点

  • 指定回调函数的方式更灵活
    旧的:必须在启动异步任务前指定
    promise:启动异步任务 => 返回promie对象 => 给promise对象绑定回调函 数(甚至可以在异步任务结束后指定/多个)

  • 支持链式调用,可以解决回调地狱问题
    回调地狱即回调函数嵌套调用,会造成代码不便于阅读、不便于异常处理的问题

# 缺点

  • 无法取消 promise,一旦新建就会立即执行,而无法中途取消
  • 不指定回调函数就没办法获取到 promise 内部的错误
  • 当 promise 处于 pending 状态时,无法得知具体情况,不知道距离完成还差多少

# async / await

  • async 函数
    async 函数即被 async 修饰的函数,其返回值是一个 Promise 对象,且 Promise 对象的状态由函数执行的返回值确定
async function request(){

} 
  • await 表达式
  1. 当 await 的右侧为 Promise 对象时,其值等于 promise 成功的值
let test = async () => {
  let res = await new Promise((resolve, reject) => {
    resolve(111)
  })

  console.log(res)
}

test()  // 111
  1. 当 await 的右侧为其他值时,直接将该值作为返回值
async function test(){
  let res = await 10
  console.log(res)
}

test() // 10
  1. await 只能用在 async 函数中
  2. await 修饰的 promise 如果失败了,需要用 try catch 捕捉
async function test(){
  try {
    let res = await Promise.reject('error')
    console.log(res)
  } catch (error) {
    console.log('error: ', error)
  }
}

test()  // error: error
  • 优缺点
    async / await 简化了 promise 的 then 调用链,不需要用回调函数处理。但是因为 await 将异步代码改造成了同步代码,如果多个异步代码没有依赖性却使用了 await 会导致性能上的降低