Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

手写Promise #10

Open
luichooy opened this issue Sep 15, 2019 · 0 comments
Open

手写Promise #10

luichooy opened this issue Sep 15, 2019 · 0 comments

Comments

@luichooy
Copy link
Owner

function resolve_promise(promise, result, resolve,reject){
  if(result === promise){
    reject(new TypeError('Chaining cycle detected for promise'))
    return
  }

  if(result instanceof MyPromise){
    result.then(res => {
      resolve_promise(result, res, resolve, reject)
    }, error => {
      reject(error)
    })
    return
  }

  // result 是函数或者对象
  if(result !== null && (typeof result === 'function' || typeof result === 'object')){
    let called = false
    try {
      let then = result.then

      if(typeof then === 'function'){
        then.call(result, res => {
          if(called) return
          called = true
          resolve_promise(promise, res, resolve, reject)
        }, error => {
          if(called) return
          called = true
          reject(error)
        })
      }else{
        // 如果then不是一个函数,直接resolve
        resolve(result)
      }
    }catch(e){
      if(called) return
      called = true
      reject(e)
    }
  }else{
    resolve(x)
  }
}

function MyPromise(executor){
  this.status = 'pending'

  this.data = null
  this.reason = null
  this.resolvedCallbacks = []
  this.rejectedCallbacks = []

  const resolve = data => {
    if(this.status === 'pending'){
      this.status = 'fulfilled'
      this.data = data
      this.resolvedCallbacks.forEach(fn => fn(this.data))
    }
  }

  const reject = reason => {
    if(this.status === 'pending'){
      this.status = 'rejected'
      this.reason = reason
      this.rejectedCallbacks.forEach(fn => fn(this.reason))
    }
  }

  exector(resolve, reject)
}

MyPromise.prototype.then = function(onResolved, onRejected){
  let promise
  if(this.status === 'pending'){
    promise = new MyPromise((resolve, reject) => {
      function resolvedFn (data){
        let res = onResolved(data)
        resolve_promise(promise, res, resolve, reject)
      }

      function rejectedFn(reason){
        let res = onRejected(reason)
        resolve_promise(promise, res, resolve, reject)
      }

      this.resolvedCallbacks.push(resolveFn)
      this.rejectedCallbacks.push(rejectedFn)
    })
  }

  if(this.status === 'fulfilled'){
    promise = new MyPromise((resolve,reject) => {
      setTimeout(() => {
        let res = onResolved(this.data)
        resolve_promise(promise, res, resolve, reject)
      })
    })
  }

  if(this.status === 'rejected'){
    promise = new MyPromise((resolve, reject) => {
      setTimeout(() => {
        let res = onRejected(this.reason)
        resolve_promise(promise, res, resolve, reject)
      })
    })
  }

  return promise
}

MyPromise.prototype.catch = fn => {
  this.then(null, reason => {
    fn(reason)
  })
}

MyPromise.all = promises => {
  return new MyPromise((resolve, reject) => {
    let result = [],
    len = promises.length,
    total = 0

    for(let i = 0; i < len; i++){
      promise[i].then(res => {
        result[i] = res
        total++
        if(total === len){
          resolve(result)
        }
      }, error => {
        reject(error)
      })
    }
  })
}

MyPromise.race = promises => {
  return new MyPromise((resolve, reject) => {
    promises.forEach(promise => {
      promise.then(resolve, reject)
    })
  })
}

MyPromise.resolve = res => {
  return new MyPromise((resolve, reject) => {
    resolve(res)
  })
}

MyPromise.reject = reason => {
  return new MyPromise((resolve, reject) => {
    reject(reason)
  })
}

包教包会,和你实现一个Promise

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant