Promise

#js

Promise出现解决了什么问题

  • 处理异步函数,返回的结果给到的是setTimeout,给不到外层函数需要自己去设计好回调函数 自己设计的回调函数自己设计的回调函数

Promise的基本使用

Promise是一个类

入参为函数(称为executor,立即执行)
resolve 成功时回调
reject 失败时回调 Promise的基本使用Promise的基本使用

Promise的三种状态

  • pending
  • fulfilled
  • rejected Promise的三种状态Promise的三种状态

Promise的对象方法

  • then
  • catch
  • finally 最终状态不论是fulfilled还是rejected,都会执行finally

可以被多次调用,Promise状态由回调函数的返回值决定

Promise的类方法

  • resolve
  • reject
  • all 有一个Promise状态为rejected就会中断,根据数组的顺序了不按照时间返回结果
  • allSettled 返回所有的状态和结果
  • race 最快的
  • any 等到一个fulfilled结果 Promise的类方法Promise的类方法

手写Promise

Promise的结构设计

Promise类包含一个State和Result
构造函数里面的函数私有,class类里面的函数公共

// 定义resolve,reject函数
// 执行传入的executor函数,并传入resolve和reject作为参数
// 执行 executor 函数:
// 调用resolve,reject函数
// 构造函数执行完毕,afe1实例创建完成

const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected'

class Afe1Promise {
  constructor(executor){
    this.status = PROMISE_STATUS_PENDING
    this.value = undefined
    this.reason = undefined

    const resolve = (value) => {
      if (this.status === PROMISE_STATUS_PENDING) {
        this.status = PROMISE_STATUS_FULFILLED
        this.value = value
        console.log("resolve被调用")
      }
    }

    const reject = (reason) => {
      if(this.status === PROMISE_STATUS_PENDING){
        this.status = PROMISE_STATUS_REJECTED
        this.reason = reason
        console.log('reject被调用');
      }
    }

    executor(resolve,reject)

  }
}

const afe1 = new Afe1Promise((resolve,reject) => {
  console.log('executor立刻执行');
  resolve('调用构造函数里面的resolve函数');
  reject('调用构造函数里面的reject函数')
})

Promise的结构设计Promise的结构设计

Promise-then方法实现

then方法设计

实例调用then方法将传入的onFulfilled和onRejected回调函数直接赋值给了this.onFulfilled和this.onRejected,给实例属性添加了两个函数(主任务)
在构造函数中,当Promise状态改变时,会调用这些存储的回调函数(微任务)

const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected'

class Afe1Promise {
  constructor(executor){
    this.status = PROMISE_STATUS_PENDING
    this.value = undefined
    this.reason = undefined

    const resolve = (value) => {
      if (this.status === PROMISE_STATUS_PENDING) {
        this.status = PROMISE_STATUS_FULFILLED
        queueMicrotask(() => {
          this.value = value
          this.onFulfilled(this.value)
        })
      }
    }

    const reject = (value) => {
      if(this.status === PROMISE_STATUS_PENDING){
        this.status = PROMISE_STATUS_REJECTED
        queueMicrotask(() => {
          this.reason = value
          this.onRejected(this.reason)
        })
      }
    }

    executor(resolve,reject)

  }

  then(onFulfilled,onRejected){
    this.onFulfilled = onFulfilled
    this.onRejected = onRejected
  }
}

const afe1 = new Afe1Promise((resolve,reject) => {
  console.log('executor立刻执行');
  resolve('调用构造函数里面的resolve函数');
})


afe1.then((res) => {
  console.log('then回调函数执行了');
  console.log(res);
})

then方法设计then方法设计

then方法设计优化一

实现多次then调用,确保status状态只能改变一次

const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected'

class Afe1Promise {
  constructor(executor){
    this.status = PROMISE_STATUS_PENDING
    this.value = undefined
    this.reason = undefined
    this.onFulfilledFns = []
    this.onRejectedFns = []

    const resolve = (value) => {
      if (this.status === PROMISE_STATUS_PENDING) {
        queueMicrotask(() => {
          if (this.status !== PROMISE_STATUS_PENDING) return
          this.status = PROMISE_STATUS_FULFILLED
          this.value = value
          this.onFulfilledFns.forEach((fn) => {
            fn(this.value)
          })
        })
      }
    }

    const reject = (reason) => {
      if(this.status === PROMISE_STATUS_PENDING){
        queueMicrotask(() => {
          if (this.status !== PROMISE_STATUS_PENDING) return
          this.status = PROMISE_STATUS_REJECTED
          this.reason = reason
          this.onRejectedFns.forEach((fn) => {
            fn(this.reason)
          })
        })
      }
    }

    executor(resolve,reject)

  }

  then(onFulfilled,onRejected){
    if(this.status === PROMISE_STATUS_FULFILLED && onFulfilled){
      onFulfilled(this.value)
    }
    if(this.status === PROMISE_STATUS_REJECTED && onRejected){
      onRejected(this.reason)
    }
    if(this.status === PROMISE_STATUS_PENDING){
      this.onFulfilledFns.push(onFulfilled)
      this.onRejectedFns.push(onRejected)
    }
  }
}

const afe1 = new Afe1Promise((resolve,reject) => {
  console.log('executor立刻执行');
  resolve('调用构造函数里面的resolve函数');
})


afe1.then((res) => {
  console.log('then回调函数执行了1');
  console.log(res);
})

afe1.then((res) => {
  console.log('then回调函数执行了2');
  console.log(res);
})

// 在确定Promise状态之后, 再次调用then
setTimeout(() => {
  afe1.then(res => {
    console.log("res3:", res)
  }, err => {
    console.log("err3:", err)
  })
}, 1000)

then方法设计优化一then方法设计优化一

then方法设计优化二

实现then的链式调用(之前是调用then方法传入的函数,现在调用的是包装的函数)

const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected'

class Afe1Promise {
  constructor(executor){
    this.status = PROMISE_STATUS_PENDING
    this.value = undefined
    this.reason = undefined
    this.onFulfilledFns = []
    this.onRejectedFns = []

    const resolve = (value) => {
      if (this.status === PROMISE_STATUS_PENDING) {
        queueMicrotask(() => {
          if (this.status !== PROMISE_STATUS_PENDING) return
          this.status = PROMISE_STATUS_FULFILLED
          this.value = value
          this.onFulfilledFns.forEach((fn) => {
            fn(this.value)
          })
        })
      }
    }

    const reject = (reason) => {
      if(this.status === PROMISE_STATUS_PENDING){
        queueMicrotask(() => {
          if (this.status !== PROMISE_STATUS_PENDING) return
          this.status = PROMISE_STATUS_REJECTED
          this.reason = reason
          this.onRejectedFns.forEach((fn) => {
            fn(this.reason)
          })
        })
      }
    }

    try {
      executor(resolve, reject)
    } catch (err) {
      reject(err)
    }

  }

  then(onFulfilled,onRejected){
    return new Afe1Promise((resolve,reject) => {
      if(this.status === PROMISE_STATUS_FULFILLED && onFulfilled){
        try {
          const value = onFulfilled(this.value)
          resolve(value)
        } catch(err) {
          reject(err)
        }
      }
      if(this.status === PROMISE_STATUS_REJECTED && onRejected){
        try {
          const reason = onRejected(this.reason)
          resolve(reason)
        } catch(err) {
          reject(err)
        }
      }
      if(this.status === PROMISE_STATUS_PENDING){
        this.onFulfilledFns.push(() => {
          try {
            const value = onFulfilled(this.value)
            resolve(value)
          } catch(err) {
            reject(err)
          }
        })
        this.onRejectedFns.push(() => {
          try {
            const reason = onRejected(this.reason)
            resolve(reason)
          } catch(err) {
            reject(err)
          }
        })
      }
    })
  }
}

const afe1 = new Afe1Promise((resolve,reject) => {
  console.log('executor立刻执行');
  resolve('调用构造函数里面的resolve函数');
})


afe1.then((res) => {
  console.log('then回调函数执行了1');
  console.log(res);
})

afe1.then((res) => {
  console.log('then回调函数执行了2');
  console.log(res);
})

// 在确定Promise状态之后, 再次调用then
setTimeout(() => {
  afe1.then(res => {
    console.log("res3:", res)
  }, err => {
    console.log("err3:", err)
  })
}, 1000)

// 调用then方法多次调用
afe1.then(res => {
  console.log("res1:", res)
  return "aaaa"
  // throw new Error("err message")
}, err => {
  console.log("err1:", err)
  return "bbbbb"
  // throw new Error("err message")
}).then(res => {
  console.log("res2:", res)
}, err => {
  console.log("err2:", err)
})

then方法设计优化二then方法设计优化二