# Promise源码

    const PENDING = 'pending'
    const FULFILLED = 'fulfilled'
    const REJECTED = 'rejected'
    class Primose {
      constructor(exector) {
        this.state = PENDING
        this.value = undefined
        this.reason = undefined
        this.onResolvedCbs = []
        this.onRejectedCbs = []
        const resolve = data => {
          if (data instanceof Promise) {
            return data.then(resolve, reject)
          }
          if (this.state === PENDING) {
            this.state = FULFILLED
            this.value = data
            this.onResolvedCbs.forEach(fn => fn())
          }
        }
        const reject = err => {
          if (this.state === PENDING) {
            this.state = REJECTED
            this.reason = err
            this.onRejectedCbs.forEach(fn => fn())
          }
        }
        try {
          exector(resolve, reject)
        } catch (e) {
          reject(e)
        }
      }
    
      then(onFulfiled, onRejected) {
        onFulfiled = typeof onFulfiled === 'function' ? onFulfiled : data => data
        onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err }
        const p2 = new Promise((resolve, reject) => {
          if (this.state === FULFILLED) {
            setTimeout(() => {
              try {
                const x = onFulfiled(this.value)
                resolvePromise(p2, x, resolve, reject)
              } catch (e) {
                reject(e)
              }
            }, 0)
          }
          if (this.state === REJECTED) {
            setTimeout(() => {
              try {
                const x = onRejected(this.reason)
                resolvePromise(p2, x, resolve, reject)
              } catch (e) {
                reject(e)
              }
            }, 0)
          }
          if (this.state === PENDING) {
            this.onResolvedCbs.push(() => {
              setTimeout(() => {
                try {
                  const x = onFulfiled(this.value)
                  resolvePromise(p2, x, resolve, reject)
                } catch (e) {
                  reject(e)
                }
              }, 0)
            })
            this.onRejectedCbs.push(() => {
              setTimeout(() => {
                try {
                  const x = onRejected(this.reason)
                  resolvePromise(p2, x, resolve, reject)
                } catch (e) {
                  reject(e)
                }
              }, 0)
            })
          }
        })
        return p2
      }
    
      catch(err){
        return this.then(null, err)
      }
    
      finally(fn){
        return this.then(data=>{
          // 如果fn返回的是promise需要等promise resolve的结果后再then
          return Promise.resolve(fn()).then(()=>data)
        },err=>{
          // 使用 Promise.resolve 就是为了防止fn是promise,后面的then必须用成功的回调去抛错
          // return Promise.resolve(fn()).then(null,()=>{throw err}) // then 这样不行是因为 fn的返回结果会直接进到下一个then的成功回调里而不是失败回调
          return Promise.resolve(fn()).then(()=>{throw err})
        })
      }
    
      static resolve(data) {
        if(data instanceof Promise){
          return data
        }
        return new Promise((resolve, reject) => {
          resolve(data)
        })
      }
    
      static reject(err){
        return new Promise((resolve, reject) => {
          reject(err)
        });
      }
    
      static all(ary){
        ary = ary || []
        const res = []
        return new Promise((resolve, reject) => {
          if(!ary.length) {
            resolve(res)
            return 
          };
          let time = 0
          for (let i = 0; i < ary.length; i++) {
            const p = ary[i];
            // p是promise
            processData(i,p)
          }
          function processData(i,p) {
            if(p && (typeof p.then === 'function')){
              p.then(data=>{
                processData(i,data)
              },reject)
            }else{
              res[i] = p
              if(++time === ary.length) resolve(res)
            }
          }
        });
      }
    
      static race(ary){
        ary = ary || []
        return new Promise((resolve,reject)=>{
          for(let i = 0;i<ary.length;i++){
            processData(ary[i])
          }
          function processData(val){
            if(val && typeof val.then === 'function'){
              val.then(data=>{
                processData(data)
              }).catch(err=>{
                reject(err)
              })
            }else{
              resolve(val)
            }
          }
        })
      }
    }
    
    function resolvePromise(p2, x, resolve, reject) {
      if (p2 === x) {
        return reject(new TypeError('循环引用'))
      }
      if (x && (typeof x === 'object' || typeof x === 'function')) {
        let called
        try {
          const then = x.then
          if (typeof then === 'function') {
            then.call(x, y => {
              if (called) return
              called = true
              resolvePromise(p2, y, resolve, reject)
            }, r => {
              if (called) return
              called = true
              reject(r)
            })
          } else {
            resolve(x)
          }
        } catch (e) {
          if (called) return
          called = true
          reject(e)
        }
      } else {
        resolve(x)
      }
    }
    
    上次更新: 7/11/2021, 7:46:45 PM