Skip to content
On this page

Promise A+实现

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

function resolvePromise(promise2, x, resolve, reject) {
  // 如果then返回的promise和x是同一个,那么就会造成死循环
  if(promise2 === x) {
    return reject(new TypeError('TypeError: Chaining cycle detected for promise #<Promise>'))
  }
  if((typeof x === 'object' && x !== null) || (typeof x === 'function')) {
    let called = false
    try {
      const then = x.then
      if(typeof then === 'function') {
        then.call(x, y => {
          if(called) return
          called = true
          resolvePromise(promise2, y, resolve, reject)
        }, e => {
          if(called) return
          called = true
          reject(e)
        })
      }else {
        resolve(x)
      }
    }catch(e) {
      if(called) return
      called = true
      reject(e)
    }
  }else {
    resolve(x)
  }
}

class Promise {
  constructor(executor) {
    this.status = PENDING
    this.value = undefined
    this.reason = undefined
    this.onResolvedCallbacks = []
    this.onRejectedCallbacks = []
    const resolve = (value) => {
      if(value instanceof Promise) {
        return value.then(resolve, reject)
      }
      if(this.status === PENDING) {
        this.status = FULFILLED
        this.value = value
        this.onResolvedCallbacks.forEach(fn => fn(this.value))
      }
    }
    
    const reject = (reason) => {
      if(this.status === PENDING) {
        this.status = REJECTED
        this.reason = reason
        this.onRejectedCallbacks.forEach(fn => fn(this.reason))
      }
    }
    try {
      executor(resolve, reject)
    }catch(e) {
      reject(e)
    }
  }
  then(onFulfilled, onRejected) {
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v
    onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err }
    const promise2 = new Promise((resolve, reject) => {
      if(this.status === PENDING) {
        this.onResolvedCallbacks.push(() => {
          queueMicrotask(() => {
            try {
              let x = onFulfilled(this.value)
              resolvePromise(promise2, x, resolve, reject)
            }catch(e) {
              reject(e)
            }
          })
        })
        this.onRejectedCallbacks.push(() => {
          queueMicrotask(() => {
            try {
              let x = onRejected(this.reason)
              resolvePromise(promise2, x, resolve, reject)
            }catch(e) {
              reject(e)
            }
            // resolvePromise(promise2, x, resolve, reject)
          })     
        })
      }else if(this.status === FULFILLED) {
        queueMicrotask(() => {
          try {
            let x = onFulfilled(this.value)
            resolvePromise(promise2, x, resolve, reject)
          }catch(e) {
            reject(e)
          }
          
        })     
      }else if(this.status === REJECTED){
        queueMicrotask(() => {
          try {
            let x = onRejected(this.reason)
            resolvePromise(promise2, x, resolve, reject)
          }catch(e) {
            reject(e)
          }
          
          
          // resolvePromise(promise2, x, resolve, reject)
        })     

      }
    })
    return promise2
    
  }
}

Promise A+测试

npm insall promises-aplus-tests -g

js
// 在实现的promise最下面添加这段函数
Promise.deferred = function(){
  let dfd = {}
  dfd.promise = new Promise((resolve,reject)=>{
      dfd.resolve = resolve;
      dfd.reject = reject
  })
  return dfd
}

module.exports = Promise

执行命令 promises-aplus-tests promise.js

Promise方法实现

catch方法实现

js
class Promise {
  ...
  catch(onRejected) {
    // 利用promise透传的特性
    return this.then(null, onRejected)
  }
}

resolve方法实现

js
class Promise {
  constructor(executor) {
    ...
    const resolve = value => {
      // 如果resolve的是一个promise 调用该promise的then
      if(value instanceof Promise) {
        return value.then(resolve, reject)
      }
      ...
    }
  }
  ...
  static reject(reason) {
    return new Promise((resolve, reject) => {
      reject(reason)
    })
  }
}

reject方法实现

js
class Promise {
  static reject(reason) {
    return new Promise((resolve, reject) => {
      reject(reason)
    })
  }
}

all方法实现

js
class Promise {
  ...
  static all(arr) {
    let len = arr.length
    const ret = []
    return new Promise((resolve, reject) => {
      arr.forEach((item, index) => {
        Promise.resolve(item).then(data => {
          ret[index] = data
          if(--len === 0) resolve(ret)
        }, reject)
      })
    })
  }
}

race方法实现

js
class Promise {
  ...
  static race(arr) {
    return new Promise((resolve, reject) => {
      arr.forEach((item, index) => {
        Promise.resolve(item).then(resolve, reject)
      })
    })
  }
}

Released under the MIT License.