MJingv / jehol-person-blog

Jehol's Blog 🙋 (hexo+react)
https://mjingv.github.io/JeholBlog/
0 stars 1 forks source link

promise再忘是孙子 #3

Open MJingv opened 5 years ago

MJingv commented 5 years ago

原理及实现

MJingv commented 4 years ago
Promise.myall = (list) => {
  let res = []
  return new Promise(resolve => {
    list.map((val, index) => {
      val.then(r => {
        res.push(r)
      })
    })
    resolve(res)
  })
}
MJingv commented 4 years ago

step1 同步版本

const PEDING = 'pending'
const REJECT = 'reject'
const RESOLVE = 'resolve'

class MyPromise {
  constructor (fn) {//传入fn执行!!!
    this.status = PEDING
    this.value = null//参数
    const resolve = (val) => {
      if (this.status == PEDING) {
        this.status = RESOLVE
        this.value = val
      }
    }
    const reject = (val) => {
      if (this.status == PEDING) {
        this.status = REJECT
        this.value = val
      }
    }
    try {
      fn(resolve, reject)//执行啊!!!
    } catch (e) {
      reject(e)
    }
  }

  then (onFull, onReject) {
    if (this.status == RESOLVE) {
      onFull(this.value)
    }
    if (this.status == REJECT) {
      onReject(this.value)
    }
  }
}

let p = new MyPromise(res => {
  res('jehol')
}).then(res => console.log(res + '!'))
MJingv commented 4 years ago

step2 异步版本

const PEDING = 'pending'
const REJECT = 'reject'
const RESOLVE = 'resolve'

class MyPromise {
  constructor (fn) {//传入fn执行!!!
    this.status = PEDING
    this.value = null//参数
    this.sucList = []
    this.errList = []
    const resolve = (val) => {
      if (this.status == PEDING) {
        this.status = RESOLVE
        this.value = val
        this.sucList.map(cb => cb())
      }
    }
    const reject = (val) => {
      if (this.status == PEDING) {
        this.status = REJECT
        this.value = val
        this.errList.map(cb => cb())
      }
    }
    try {
      fn(resolve, reject)//执行啊!!!
    } catch (e) {
      reject(e)
    }
  }

  then (onFull, onReject) {
    if (this.status == RESOLVE) {
      onFull(this.value)
    }
    if (this.status == REJECT) {
      onReject(this.value)
    }
    if (this.status == PEDING) {
      this.sucList.push(() => {onFull(this.value)})
      this.errList.push(() => {onReject(this.value)})
    }
  }
}

let p = new MyPromise(res => {
  setTimeout(() => { res('jehol')}, 1000)
}).then(res => console.log(res + '!'))
MJingv commented 4 years ago

step3 链式调用版本

const PEDING = 'pending'
const REJECT = 'reject'
const RESOLVE = 'resolve'

class MyPromise {
  constructor (fn) {//传入fn执行!!!
    this.status = PEDING
    this.value = null//成功参数
    this.reason = null//失败参数
    this.sucList = []
    this.errList = []
    const resolve = (val) => {
      if (this.status == PEDING) {
        this.status = RESOLVE
        this.value = val
        this.sucList.map(cb => cb())
      }
    }
    const reject = (val) => {
      if (this.status == PEDING) {
        this.status = REJECT
        this.value = val
        this.errList.map(cb => cb())
      }
    }
    try {
      fn(resolve, reject)//执行啊!!!
    } catch (e) {
      reject(e)
    }
  }

  then (onFull, onReject) {
    onFull = typeof onFull == 'function' ? onFull : () => onFull
    onReject = typeof onFull == 'function' ? onReject : () => onReject
    return new MyPromise((resolve, reject) => {
      if (this.status == RESOLVE) {
        let r = onFull(this.value)
        if (r instanceof MyPromise) {
          r.then(resolve, reject)
        } else {
          resolve(r)
        }
      }
      if (this.status == REJECT) {
        let r = onReject(this.reason)
        if (r instanceof MyPromise) {
          r.then(resolve, reject)
        } else {
          reject(r)
        }
      }
      if (this.status == PEDING) {
        this.sucList.push(() => {
          let r = onFull(this.value)
          if (r instanceof MyPromise) {
            r.then(resolve, reject)
          } else {
            resolve(this.value)
          }
        })
        this.errList.push(() => {
          let r = onReject(this.reason)
          if (r instanceof MyPromise) {
            r.then(resolve, reject)
          } else {
            onReject(this.reason)
          }
        })
      }
    })
  }
}

let p = new MyPromise(res => {
  console.log(1)
  setTimeout(() => { res('jehol')}, 1000)
}).then(res => setTimeout(() => { console.log(res + '!')}, 1000))