promise详解

x33g5p2x  于2022-03-08 转载在 其他  
字(7.8k)|赞(0)|评价(0)|浏览(294)

一、写在前面
本文主要总结Promise的相关知识,主要分为两个部分,一个是对于Promsieapi使用。另一个是对于手写Promise。完全解决面试问题。Promise主要分为三种状态,一个是pendding,一个是fulfillled,另一个是rejected
二、Promise api的使用
2.1、promise的then方法

//1、then中没有返回值,则会使用promise包裹undefined进行返回。
let promise = new Promise((resolve, reject) => {
  resolve('hhhh')
}).then(res => {
  console.log(res)  //hhhh
}).then(ret => {
  console.log(ret)  //undefined
})

//2、如果直接使用return一个值,则会在外部包裹一层promise
let promise = new Promise((resolve, reject) => {
  resolve("hhhh")
}).then(res => {
  console.log(res)   //hhhh
  return "next one"
}).then(res => {
  console.log(res)   //next one
})

//3、如果直接return promise,则会将Promise返回的结果传递下去
let promise = new Promise((resolve, reject) => {
  resolve("hhhh")
}).then(res => {
  console.log(res)   //hhhh
  return new Promise((resolve, reject) => {
    resolve("next one")
  })
}).then(res => {
  console.log(res)   //next one
})

//4、也可以是thenable对象
let promise = new Promise((resolve, reject) => {
  resolve("hhhh")
}).then(res => {
  console.log(res)   //hhhh
  return {
    then(resolve, reject) {
      resolve("next one")
    }
  }
}).then(res => {
  console.log(res)   //next one
})

//5、如果一个promsie出现多个then则都是会执行的。
let promise = new Promise((resolve, reject) => {
  resolve("hhhh")
})

promise.then(res => {
  console.log(res + "第一个")  //hhhh第一个
})

promise.then(res => {
  console.log(res + "第二个")  //hhhh第二个
})

2.2、catch方法

//1、直接通过new Error报错,导致阅读性差
let promise = new Promise((resolve, reject) => {
  throw new Error('err message')
})
promise.then(res => {
  console.log(res)
}, err => {
  console.log(err.name)    //Error
})

//2、把catch放在最后,如果整条promsie链路上存在错误,则就会执行catch函数中的内容。
let promise = new Promise((resolve, reject) => {
  resolve('大家好')
  // reject('er')
}).then(res => {
  console.log(res)   //大家好
  return new Promise((resolve, reject) => {
    // resolve('急急急')
    reject('hhjhh') 
  })
}).catch(err => {
  console.log(err)  //hhjhh
})

//3、catch执行完之后也会返回一个promsie对象
let promise = new Promise((resolve, reject) => {
  // resolve('hello world')
  reject('message err')
})
promise.then(res => {
  console.log(res)
}).catch(err => {
  console.log(err)   //message err
  return 'hek'
}).then(ret => {
  console.log(ret)  //hek
}).catch(err => {
  console.log(err)
})

2.3、finnally方法

let promise = new Promise((resolve, reject) => {
  // resolve("大家")
  reject('sss')
})
promise.then(res => {
  console.log(res)
}).catch(err => {
  console.log(err)   //sss
}).finally(() => {
  console.log('hello finnally')  //hello finnally
})
//finally中的函数,在最后才执行

2.4、Promise.resolve()

//也就相当于
new Promise((resolve, reject) => {
  resolve("hhhhh")
})

2.5、Promise.reject()

//也就相当于
new Promise((resolve, reject) => {
	reject('hhhhh')
})

2.6、Promise.all

//1、Promise.all()中传入一个数组,并且数组中的元素可以默认可以转化为Promise,假如是字符串'12s',则会
//转化为new Promise((resolve, reject) => { resolve('12s') })
//2、Promise.all()传入的数组中,如果存在reject的,则直接执行catch中的回调函数,如果不存在reject的,则直接执行then。
//3、Promise.all如果出现错误的情况,则直接返回第一错误的内容。

例子一:
let promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('111')
  }, 1000)
})
let promise2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('222')
  }, 2000)
})
let promise3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('333')
  }, 3000)
})

Promise.all([promise1, promise2, promise3]).then(res => {
  console.log(res)  //['111','222','333']
}).catch(err => {
  console.log(err)
})

例子二:
let promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('111')
  }, 1000)
})
let promise2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject("222")
  }, 2000)
})
let promise3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('333')
  }, 3000)
})

Promise.all([promise1, promise2, promise3]).then(res => {
  console.log(res) 
}).catch(err => {
  console.log(err)  //222
})

2.7、Promise.allSettled

//Promise.allSettled返回的是状态对象。

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

let promise2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('222')
  }, 2000)
})

let promise3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject('333')
  }, 3000)
})

Promise.allSettled([promise1, promise2, promise3]).then(res => {
  console.log(res)
})
/*
[
  { status: 'fulfilled', value: '111' },
  { status: 'fulfilled', value: '222' },
  { status: 'rejected', reason: '333' } 
]
*/

2.8、Promise.race()

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

let promise2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('222')
  }, 2000)
})

let promise3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject('333')
  }, 3000)
})

Promise.race([promise1, promise2, promise3]).then(res => {
  console.log(res)
}).catch(err => {
  console.log('err' + err)  //err111(并且也会等待三秒才会结束)
})

//race是拿到最先出来的结构,不论结果是resolve还是reject。

2.9、Promse.any

//1、Promise.any表示只要返回一个即可,如果全都是reject的,则直接执行catch中的回调函数
//2、Promise.any是在es12中新增的目前node可能不支持,所以需要在浏览器环境下执行。
let promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject('111')
  }, 1000)
})

let promise2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject('222')
  }, 2000)
})

let promise3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject('333')
  }, 3000)
})

Promise.any([promise1,promise2, promise3]).then(res => {
  console.log(res)
}).catch(err => {
  console.log(err.errors)  //['111','222','333']
})

三、手写Promise

// 定义三个常量
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_PENDDING = 'pendding'
const PROMISE_STATUS_REJECTED = 'rejected'

function execFunc(func, value, resolve, reject) {
  try {
    let res = func(value)
    resolve(res)
  } catch (err) {
    reject(err)
  }
}

class MyPromise {
  constructor(exacutor) {
    this.status = PROMISE_STATUS_PENDDING
    this.reason = undefined
    this.value = undefined
    this.onFulfilledFns = []
    this.onRejectedFns = []

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

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

    exacutor(resolve, reject)
  }
  then(onFulfilled, onRejected) {
    onRejected = onRejected || (err => {
      throw err
    })
    return new MyPromise((resolve, reject) => {

      if (this.status === PROMISE_STATUS_FULFILLED) {
        if (onFulfilled) execFunc(onFulfilled, this.value, resolve, reject)
      }

      if (this.status === PROMISE_STATUS_REJECTED) {
        if (onRejected) execFunc(onRejected, this.reason, resolve, reject)
      }

      if (this.status === PROMISE_STATUS_PENDDING) {
        if (onFulfilled) this.onFulfilledFns.push(() => {
          execFunc(onFulfilled, this.value, resolve, reject)
        })
        if (onRejected) this.onRejectedFns.push(() => {
          execFunc(onRejected, this.reason, resolve, reject)
        })
      }
    })
  }

  // catch方法
  catch (onRejected) {
    return this.then(undefined, onRejected)
  }
  // finally方法
  finnally(onFinial) {
    this.then(() => {
      onFinial()
    }, () => {
      onFinial()
    })
  }

  // 实现MyPromise.resolve()方法
  static resolve(value) {
    return new MyPromise((resolve, reject) => {
      resolve(value)
    })
  }

  // 实现MyPromise.reject()方法
  static reject(reason) {
    return new MyPromise((resolve, reject) => {
      reject(reason)
    })
  }

  // 实现MyPromise.all()方法
  static all(promises) {
    return new MyPromise((resolve, reject) => {
      let arr = []
      promises.forEach(item => {
        item.then(res => {
          arr.push(res)
          if (arr.length === promises.length) {
            resolve(arr)
          }
        }, err => {
          reject(err)
        })
      })
    })
  }

  // 实现MyPromise.allSettle()
  static allsettle(promises) {
    return new MyPromise((resolve, reject) => {
      let arr = []
      promises.forEach(item => {
        item.then(res => {
          arr.push({
            value: res,
            status: PROMISE_STATUS_FULFILLED
          })
          if(arr.length === promises.length) {
            resolve(arr)
          }
        }, err => {
          arr.push({
            value: err,
            status: PROMISE_STATUS_REJECTED
          })
          if(arr.length === promises.length) {
            resolve(arr)
          }
        })
      })
    })
  }

  // 实现MyPromise.race()方法
  static race(promises) {
    return new MyPromise((resolve, reject) => {
      promises.forEach(item => {
        item.then(res => {
          resolve(res)
        }, err => {
          reject(err)
        })
      })
    })
  }

  // 实现MyPromise.any()方法
  static any(promises) {
    return new MyPromise((resolve, reject) => {
      let arr = []
      promises.forEach(item => {
        item.then(res => {
          resolve(res)
        }, err => {
          arr.push(err)
          if(arr.length === promises.length) {
            reject(new AggregateError(arr))
          }
        })
      })
    })
  }
}

相关文章