Skip to content

Promise使用与原理

js
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

class MyPromise {
  constructor(executor) {
    try {
      executor(this.resolve, this.reject)
    } catch (error) {
      this.reject(error)
    }
  }

  status = PENDING

  value = null
  reason = null

  onFulfilledCallback = []
  onRejectedCallback = []

  resolve = (value) => {
    if (this.status == PENDING) {
      this.status = FULFILLED
      this.value = value

      while (this.onFulfilledCallback.length) {
        const cb = this.onFulfilledCallback.shift()
        cb(value)
      }
    }
  }

  reject = (reason) => {
    if (this.status == PENDING) {
      this.status = REJECTED
      this.reason = reason

      while (this.onRejectedCallback.length) {
        const cb = this.onRejectedCallback.shift()
        cb(reason)
      }
    }
  }

  static resolve(param) {
    if (param instanceof MyPromise) return param
    return new MyPromise((resolve) => resolve(param))
  }

  static reject(param) {
    if (param instanceof MyPromise) return param
    return new MyPromise((resolve, reject) => reject(param))
  }

  then = (onFulfilled, onRejected) => {
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value
    onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }

    const _promise = new MyPromise((resolve, reject) => {
      if (this.status == FULFILLED) {
        queueMicrotask(() => {
          try {
            const x = onFulfilled(this.value)
            resolvePromise(_promise, x, resolve, reject)
          } catch (error) {
            reject(error)
          }
        })
      } else if (this.status == REJECTED) {
        queueMicrotask(() => {
          try {
            const x = onRejected(this.reason)
            resolvePromise(_promise, x, resolve, reject)
          } catch (error) {
            reject(error)
          }
        })
      } else if (this.status == PENDING) {
        // 异步进行缓存回调函数
        this.onFulfilledCallback.push(() => {
          queueMicrotask(() => {
            try {
              const x = onFulfilled(this.value)
              resolvePromise(_promise, x, resolve, reject)
            } catch (error) {
              reject(error)
            }
          })
        })
        this.onRejectedCallback.push(() => {
          queueMicrotask(() => {
            try {
              const x = onRejected(this.reason)
              resolvePromise(_promise, x, resolve, reject)
            } catch (error) {
              reject(error)
            }
          })
        })
      }
    })
    return _promise
  }
}

function resolvePromise(self, x, resolve, reject) {
  if (self === x) {
    return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
  }
  if (x instanceof MyPromise) {
    try {
      x.then(resolve, reject)
    } catch (error) {
      reject(error)
    }
  } else {
    resolve(x)
  }
}

const promise = new MyPromise((resolve, reject) => {
  console.log('init Promsie')
  setTimeout(() => {
    resolve(1)
  })
})

promise
  .then((v1) => {
    console.log(v1)
    return 2
  })
  .then((v2) => {
    console.log(v2)
    return new MyPromise((resolve) => resolve(3))
  })
  .then((v) => {
    console.log(v)
    console.log('end')
  }, reason => {
    console.log(reason)
  })

MyPromise
  .resolve(new MyPromise((resolve) => resolve('static resolve')))
  .then((v) => {
    console.log(v)
    console.log('static')
  })

MyPromise
  .reject(false)
  .then(null, err => console.log(err))


MyPromise.resolve().then(() => {
  console.log(0);
  return MyPromise.resolve(4);
}).then((res) => {
  console.log(res)
})

MyPromise.resolve().then(() => {
  console.log(1);
}).then(() => {
  console.log(2);
}).then(() => {
  console.log(3);
}).then(() => {
  console.log(5);
}).then(() =>{
  console.log(6);
})

//待更新...

若您在阅读过程中发现一些错误:如语句不通、文字、逻辑等错误,可以在评论区指出,我会及时调整修改,感谢您的阅读。同时您觉得这篇文章对您有帮助的话,可以打赏作者一笔作为鼓励,金额不限,感谢支持🤝。
支付宝捐赠微信支付捐赠

Released under the MIT License.