高阶函数的应用:手写Promise源码(四)

1、优化then方法的抛异常问题
2、根据then方法接收的两个函数参数的返回值类型进行不同的数据处理

// promise/A+规范中说明promise有三种状态,且状态一旦被改变就不能再次发生变化
const PENDING = 'Pending'
const FULFILLED = 'Fulfilled'
const REJECTED = 'Rejected'
class Promise {
  // 高阶函数,函数的参数是函数,高阶函数可以实现参数的预置
  // 函数的参数中的函数为函数的声明
  // executor是立即执行的函数,参数被预置在了constructor中
  constructor(executor) {
    this.state = PENDING
    this.value = undefined         // 成功的结果
    this.reason = undefined        // 失败的理由
    
    // 解决then可以多次调用的问题
    this.onResolvedCallbacks = []   
    this.onRejectedCallbacks = []

    const resolve = (value) => {
      if(this.state === PENDING) {
        this.state = FULFILLED
        this.value = value
        // 当状态变化时再执行回调函数
        this.onResolvedCallbacks.forEach(cb => cb(value))
      }
    }

    const reject = (reason) => {
      if(this.state === PENDING) {
        this.state = REJECTED
        this.reason = reason
        // 当状态变化时再执行回调函数
        this.onRejectedCallbacks.forEach(cb => cb(reason))
      }
    }
   
    // 此处为executor函数的调用。参数传入resolve和reject两个函数
    try {
      executor(resolve, reject)
    } catch(err) {
      reject(err)
    }
  }
  then(onFulfilledCallback, onRejectedCallback) {
    onFulfilledCallback = typeof onFulfilledCallback === 'function' ? onFulfilledCallback : value => value
    // 优化抛异常
    onRejectedCallback = typeof onRejectedCallback === 'function' ? onRejectedCallback : reason => { throw reason } 

    // 可以链式调用,则then返回的必须是一个Promise
    let promise = new Promise((resolve, reject) => {
      if(this.state === FULFILLED) {
        // 优化捕捉异常
        setTimeout(() => {
          try {
            let res = onFulfilledCallback(this.value)
            // 根据res的不同类型做不同的处理
            resolvePromise(promise, res, resolve, reject)
          } catch(e) {
            reject(e)
          }
        })
      }
      
      if(this.state === REJECTED) {
        setTimeout(() => {
          try {
            let res = onRejectedCallback(this.reason)
            resolvePromise(promise, res, resolve, reject)
          } catch(e) {
            reject(e)
          }
        })
      }
      
      // 当executor出现异步任务时,then执行的时候,状态还未发生变化,可以将回调放到回调函数数组中
      if(this.state === PENDING) {
        this.onResolvedCallbacks.push((value) => {
          setTimeout(() => {
            try {
              let res = onFulfilledCallback(value)
              resolvePromise(promise, res, resolve, reject)
            } catch(e) {
              reject(e)
            }
          })
        }) 
        this.onRejectedCallbacks.push((reason) => {
          setTimeout(() => {
            try {
              let res = onRejectedCallback(reason)
              resolvePromise(promise, res, resolve, reject)
            } catch(e) {
              reject(e)
            }
          })
        })   
      }
    })
    return promise
  }
}

// 根据不同的res类型进行不同的处理
function resolvePromise(promise, res, resolve, reject) {
  if(res === promise) {
    return reject(new TypeError('死循环'))
  }

  if(res instanceof Promise) {
      try {
        res.then(x => {
          resolvePromise(promise, x, resolve, reject)
          // resolve(x)
        })
      } catch(e) {
        reject(e)
      }
  } else {
    resolve(res)
  }
}

let p = new Promise((resolve, reject) => {
	console.log(2)
	setTimeout(() => {
		resolve(1)
	}, 0)
})

let p2 = new Promise((resolve, reject) => {
  resolve(3)
})

let then = p.then(res => {
	console.log(res)
  return p2
}).then(res => {
  console.log(res)
})

console.log(5)

// 2, 5, 1, 3
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值