# Promise

# 基础术语

  • promise 是一个包含 then 方法的对象或函数,该方法符合规范指定的行为

  • thenable 是一个包含 then 方法和对象或者函数

  • value 就是任意合法 JS 值

  • exception 就是 throw 语句抛出的值

  • reason 是一个指示 promise 为什么被 rejected 的值

class myPromise {
  static PENDING = 'pending'
  static FULFILLED = 'fulfilled'
  static REJECTED = 'rejected'

  constructor(executor) {
    this.status = myPromise.PENDING
    this.result = null
    try {
      executor(this.resolve.bind(this), this.reject.bind(this))
    } catch (error) {
      this.reject(error)
    }
  }
  resolve(result) {
    if (this.status === myPromise.PENDING) {
      this.status = myPromise.FULFILLED
      this.result = result
    }
  }
  reject(result) {
    if (this.status === myPromise.PENDING) {
      this.status = myPromise.REJECTED
      this.result = result
    }
  }
  then(onResolve, onReject) {
    if (this.status === myPromise.FULFILLED) {
      onResolve(this.result)
    }
    if (this.status === myPromise.REJECTED) {
      onReject(this.result)
    }
  }
}
const p = new myPromise((resolve, reject) => {
  throw new Error(111)
})
p.then(
  (result) => {
    console.log(result)
  },
  (result) => {
    console.log(result, 'error')
  }
)

# async

  • async 表示函数里有异步操作

  • 返回值是 Promise

  • async 函数的语法规则总体上比较简单,难点是错误处理机制

# await

  • 正常情况下,await 命令后面是一个 Promise 对象,返回该对象的结果。如果不是 Promise 对象,就直接返回对应的值

# Promise.all

Promise.all 等待所有都完成(或第一个失败)。

# Promise.allSettled

当需要执行并行和独立的异步操作并收集所有结果时,Promise.allSettled() 就是不错的选择,即使一些异步操作可能失败。

function rejectTimeout(reason, delay) {
  return new Promise((r, reject) => setTimeout(() => reject(reason), delay))
}

const statusesPromise = Promise.allSettled([
  rejectTimeout(new Error('Fruits is empty'), 2000),
  rejectTimeout(new Error('Vegetables is empty'), 1000),
])

// 等待 2 秒 ...
const list = async () => {
  try {
    const statuses = await statusesPromise
    console.log(statuses)
  } catch (error) {
    console.log(error)
  }
}

list() // // [{ status: 'rejected', reason: Error('Fruits is empty') },{ status: 'rejected', reason: Error('Vegetables is empty') }]