手写Promise

1. 构造器的实现

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
  #state = PENDING
  #result = undefined
  #changeState(state, result) {
    if (this.#state !== PENDING) return
    this.#state = state
    this.#result = result
    console.log(this.#state, this.#result)
  }
  constructor(exectutor) {
    const resolve = (data) => {
      this.#changeState(FULFILLED, data)
    }
    const reject = (reason) => {
      this.#changeState(REJECTED, reason)
    }
    try {
      exectutor(resolve, reject)
    } catch (err) {
      reject(err)
    }
  }
}
​
const p = new MyPromise((resolve, reject) => {
  throw 123
})
​
console.log(p)

2. then的回调执行时机

添加then函数基本结构返回结果仍然是promise 。

但是注意如果是异步执行resolve或者reject。则promise的状态永远是pending,而then函数已经执行过,永远不会被再次执行

​
  then(onFulfilled, onRejected) {
    return new MyPromise((resolve, reject) => {
      if (this.#state === FULFILLED) {
        onFulfilled(this.#result)
      }
      if (this.#state === REJECTED) {
        onRejected(this.#result)
      }
    })
​
const p = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    resolve(1)
  }, 1000)
  // resolve(1)
})
p.then((res) => {
  console.log('promise 完成', res)
}, (err) => {
  console.log('promise 失败', err)
})    

改造then函数 ,记录onFulfilledonRejectedresolvereject四个变量。等到promise状态改变时再调用回调

将处理逻辑放入run方法中,then可以调用run方法, changeState也可以调用run方法

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
  #state = PENDING
  #result = undefined
  #handlers = []
  #changeState(state, result) {
    // 如果状态已经改变则返回。promise一旦确定状态就不会再改变
    if (this.#state !== PENDING) return
    this.#state = state
    this.#result = result
    this.#run()
  }
  #run() {
    // 如果状态挂起,先不执行代码
    if (this.#state === PENDING) return
    while (this.#handlers.length) {
      const {
        onFulfilled,
        onRejected,
        resolve,
        reject
      } = this.#handlers.shift()
      if (this.#state === FULFILLED) {
        if (typeof onFulfilled === 'function') {
          onFulfilled(this.#result)
        }
      } else {
        if (this.#state === REJECTED) {
          if (typeof onRejected === 'function') {
            onRejected(this.#result)
          }
        }
      }
    }
  }
  constructor(exectutor) {
    const resolve = (data) => {
      this.#changeState(FULFILLED, data)
    }
    const reject = (reason) => {
      this.#changeState(REJECTED, reason)
    }
    try {
      exectutor(resolve, reject)
    } catch (err) {
      reject(err)
    }
  }
  then(onFulfilled, onRejected) {
    return new MyPromise((resolve, reject) => {
      this.#handlers.push({
        onFulfilled,
        onRejected,
        resolve,
        reject
      })
      this.#run()
    })
  }
}
​
const p = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    reject(1)
  }, 1000)
  // resolve(1)
})
p.then((res) => {
  console.log('promise 完成1', res)
}, (err) => {
  console.log('promise 失败1', err)
})
p.then((res) => {
  console.log('promise 完成2', res)
}, (err) => {
  console.log('promise 失败2', err)
})
p.then((res) => {
  console.log('promise 完成3', res)
}, (err) => {
  console.log('promise 失败3', err)
})
p.then((res) => {
  console.log('promise 完成4', res)
}, (err) => {
  console.log('promise 失败4', err)
})

3. then的返回值

  1. 如果对应的回调不是函数 ,即发生穿透。值穿透指的是,链式调用的参数不是函数时,会发生值穿透,就传入的非函数值忽略,传入的是之前的函数参数。

    Promise.resolve(1)
      .then(null)
      .then((data) => { console.log( data) })
    //1
    
    Promise.resolve(1)
      .then(2)
      .then(Promise.resolve(3))
      .then((data) => { console.log( data) }) 
    // 1
    
    
      #run() {
        // 如果状态挂起,先不执行代码
        if (this.#state === PENDING) return
        while (this.#handlers.length) {
          const {
            onFulfilled,
            onRejected,
            resolve,
            reject
          } = this.#handlers.shift()
          if (this.#state === FULFILLED) {
            if (typeof onFulfilled === 'function') {
              onFulfilled(this.#result)
            } else {
              resolve(this.#result)
            }
          } else {
            if (this.#state === REJECTED) {
              if (typeof onRejected === 'function') {
                onRejected(this.#result)
              } else {
                reject(this.#result)
              }
            }
          }
        }
      }
  2. 如果对应的回调是函数,尝试运行函数并拿到返回结果

     #run() {
        // 如果状态挂起,先不执行代码
        if (this.#state === PENDING) return
        while (this.#handlers.length) {
          const {
            onFulfilled,
            onRejected,
            resolve,
            reject
          } = this.#handlers.shift()
          if (this.#state === FULFILLED) {
            if (typeof onFulfilled === 'function') {
              try {
                const data = onFulfilled(this.#result)
                resolve(data)
              } catch (err) {
                reject(err)
              }
    
            } else {
              resolve(this.#result)
            }
          } else {
            if (this.#state === REJECTED) {
              if (typeof onRejected === 'function') {
                try {
                  const data = onRejected(this.#result)
                  resolve(data)
                } catch (err) {
                  reject(err)
                }
    
              } else {
                reject(this.#result)
              }
            }
          }
        }
      }
  3. 优化重复代码#runOne

    #runOne(callback, resolve, reject) {
        if (typeof callback !== 'function') {
          const settled = this.#state === FULFILLED ? resolve : reject;
          settled(this.#result)
        } else {
          try {
            const result = callback(this.#result)
            resolve(result)
          } catch (err) {
            reject(err)
          }
        }
      }
      #run() {
        // 如果状态挂起,先不执行代码
        if (this.#state === PENDING) return
        while (this.#handlers.length) {
          const {
            onFulfilled,
            onRejected,
            resolve,
            reject
          } = this.#handlers.shift()
          if (this.#state === FULFILLED) {
            this.#runOne(onFulfilled, resolve, reject)
          } else {
            this.#runOne(onRejected, resolve, reject)
          }
        }
      }
  4. 如果回调函数返回的结果是promise ,首先需要辅助函数判断回调函数的结果是否是promise。判断then属性是否是函数

    #isPromiseLike(value) {
        if (value !== null && (typeof value === 'object' || typeof value === 'function')) {
          return typeof value.then === 'function'
        }
        return false
      }
    ​
      #runOne(callback, resolve, reject) {
        if (typeof callback !== 'function') {
          const settled = this.#state === FULFILLED ? resolve : reject;
          settled(this.#result)
          return
        } else {
          try {
            const data = callback(this.#result)
            if (this.#isPromiseLike(data)) {
              data.then(resolve, reject)
            } else {
              resolve(data)
            }
    ​
          } catch (err) {
            reject(err)
          }
        }
      }

4.微队列和PromiseLike

 #runMicroTask(func) {
    if (typeof process === "object" && typeof process.nextTick === "function") {
      process.nextTick(func);
    } else if (typeof MutationObserver === "function") {
      const ob = new MutationObserver(func)
      const textNode = document.createTextNode('1')
      ob.observe(textNode, {
        characterData: true
      })
      textNode.data = '2'
    } else {
      setTimeout(func, 0)
    }
  }
  #runOne(callback, resolve, reject) {
    this.#runMicroTask(() => {
      if (typeof callback !== 'function') {
        const settled = this.#state === FULFILLED ? resolve : reject;
        settled(this.#result)
        return
      } else {
        try {
          const data = callback(this.#result)
          if (this.#isPromiseLike(data)) {
            data.then(resolve, reject)
          } else {
            resolve(data)
          }
​
        } catch (err) {
          reject(err)
        }
      }
    })
​
  }

5. resolve和reject

  catch(onRejected) {
    return this.then(undefined, onRejected)
  }
  finally(onFinally) {
    return this.then(data => {
      onFinally();
      return data
    }, err => {
      onFinally()
      throw err
    })
  }
  /* 
    1. 判断value是否是promise 如果是直接返回
    2. 判断是否是then方法的promise如果是直接调用then方法
   */
  static resolve(value) {
    if (value instanceof MyPromise) {
      return value
    }
    let _resolve, _reject
    const p = new MyPromise((resolve, reject) => {
      _resolve = resolve
      _reject = reject
    })
    if (p.#isPromiseLike(value)) {
      value.then(_resolve, _reject)
    } else {
      _resolve(value)
    }
    return p
  }
  static reject(reason) {
    return new MyPromise((resolve, reject) => {
      reject(reason)
    })
  }

6. promise.all

  1. 静态方法返回一个promise

  2. Promise 都被兑现时,返回的 Promise 也将被兑现(即使传入的是一个空的可迭代对象),并返回一个包含所有兑现值的数组。

  3. 如果输入的任何 Promise 被拒绝,则返回的 Promise 将被拒绝,并带有第一个被拒绝的原因。

​
static all() {
    let _resolve, _reject
    const p = new MyPromise((resolve, reject) => {
      _resolve = resolve
      _reject = reject
    })
    let count = 0
    for (let param of params) {
      count++
    }
    // 空的迭代对象
    if (count === 0) {
      _resolve(result)
    }
    return p
  }
​
static all(params) {
    let _resolve, _reject
    const p = new MyPromise((resolve, reject) => {
      _resolve = resolve
      _reject = reject
    })
    let count = 0
    let fulfilledCount = 0
    const result = []
    for (let param of params) {
      let i = count
      count++
      MyPromise.resolve(param).then(data => {
        result[i] = data
        fulfilledCount++
        if (fulfilledCount === count) {
          _resolve(result)
        }
      }, _reject)
​
    }
    // 空的迭代对象
    if (count === 0) {
      _resolve(result)
    }
    return p
  }

测试

MyPromise.all([]).then(data => {
  console.log(data) //[]
})
​
MyPromise.all([1, 2, 3, 4]).then(data => {
  console.log(data) //[1, 2, 3, 4]
})
​
MyPromise.all([1, 2, 3, MyPromise.reject(4)]).then(data => {
  console.log(data)
}, (err) => {
  console.log(err) //4
})
​
MyPromise.all([1, 2, MyPromise.reject(3), MyPromise.reject(4)]).then(data => {
  console.log(data)
}, (err) => {
  console.log(err) //3
})

7. promise.race

  static race(params) {
    let _resolve, _reject
    const p = new MyPromise((resolve, reject) => {
      _resolve = resolve
      _reject = reject
    })
    let result = null
    for (let param of params) {
      MyPromise.resolve(param).then(data => {
        result = data
        _resolve(result)
      }, err => {
        _reject(err)
      })
    }
    return p
  }

测试

const p = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    resolve(1)
  }, 1000)
})
MyPromise.race([p, MyPromise.reject(3)]).then(data => {
  console.log(data)
}, (err) => {
  console.log(err) //3
}) 

  • 29
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值