1、基本架构搭建

function Promise(fn) {
    this.promiseState = 'pending' // 状态
    this.promiseResult = undefined // 结果

    var resolve = function(){

    }
    var reject = function() {

    }

    fn(resolve,reject)
}

Promise.prototype = {
    then: function() {

    }
}

 

 

 

 

 

 

 2、resolve,reject 状态的改变和结果的保存 ,并且状态改变是单向的不可逆的

 

回调函数的调用是window 所以这里要注意 this 的指向

 

 

 3、throw 抛出异常改变状态

1 var p = new Promise(function (resolve, reject) {
2     throw('抛出异常')
3 })
4 console.log(p)

当promise回调直接抛出异常的时候,直接报错,后面的代码不会执行

 

 

 所以 try catch 处理回调函数

捕获到交给 reject处理

 

 

 

 

 

 

4、then 方法

then 方法我的理解就是 当状态改变时 调用的回调函数

 两个参数,根据状态只执行一个

var p = new Promise(function (resolve, reject) {
    throw('抛出异常')
})
p.then(function(res){
    console.log(res)
},function(err){
    console.log(err)
})
console.log(p)

js

Promise.prototype = {
    then: function(onFulfilled,onRejected) {
        if(this.PromiseState === 'fulfilled'){
            onFulfilled(this.PromiseResult)
        }
        if(this.PromiseState === 'rejected'){
            onRejected(this.PromiseResult)
        }
    }
}

 

 

 

5、改为异步任务执行

这里总结,改为异步其实就是把then中的回调保存起来,等状态改变再执行

Promise.prototype = {
    then: function(onFulfilled,onRejected) {
        if(this.PromiseState === 'fulfilled'){
            onFulfilled(this.PromiseResult)
        }
        if(this.PromiseState === 'rejected'){
            onRejected(this.PromiseResult)
        }
        if(this.PromiseState === 'pending'){
            // 保存回调函数
            this.thenCallback = { onFulfilled, onRejected }
        }
    }
}

// 当状态改变 判断 thenCallback  ,然后执行

 1  var resolve = function(res){
 2         if(_this.PromiseState !== 'pending') return
 3         _this.PromiseState = 'fulfilled'
 4         _this.PromiseResult = res
 5         if(_this.thenCallback) {
 6             _this.thenCallback.onFulfilled(res)
 7         }
 8     }
 9     var reject = function(err) {
10         if(_this.PromiseState !== 'pending') return
11         _this.PromiseState = 'rejected'
12         _this.PromiseResult = err
13         if(_this.thenCallback) {
14             _this.thenCallback.onRejected(err)
15         }
16     }

当然,这里个人觉得可以优化的地方,then中只做回调函数的保存这一步的操作,回调函数的执行放到 resolve,reject (状态改变时)中执行,这样可以减少几个状态的判断

 

 

 

 6、then中多个回调的实现


当 then 多个回调的时候 我们发现 只执行了最后一个 then

 

 所以我们要弄一个 队列数组保存,

当转台改变是 执行数组中的所有函数

 if(_this.thenCallback) {
            _this.thenCallback.forEach(item => {
                item.onFulfilled(res)
            })
        }

 

 7、同步修改状态 then 方法结果返回(Promise,return,throw)

 它会返回一个新的 promise 因为久的promise 的状态已经改变了,所以旧的promise已经失效

then(onResolve, onRejected) { // 添加任务队列
    // 因为状态只能单向改变,如果之前resolve了,后面then中throw抛出异常则无法改变状态
    // 另外任务队列也不是最新的
    // 所以不能 return this
    return new mpromise((resolve, reject) => {}
}

接下来, then 里面的回调函数有两种情况,

一种返回结果

var res = p.then(function(res) {
  console.log(res)
  return 'hello promise!'
  // return new mpromise((resolve) => { resolve('success')})
}, (err) => {
  console.log(err)
})

另一种直接返回一个 promise

var res = p.then(function(res) {
  console.log(res)
  return new mpromise((resolve) => { resolve('success')})
}, (err) => {
  console.log(err)
})

还有一种是 throw 抛出错误

throw(‘1’)

 

所以要做一个区分判断

then(onResolve, onRejected) { // 添加任务队列
    // 因为状态只能单向改变,如果之前resolve了,后面then中throw抛出异常则无法改变状态
    // 另外任务队列也不是最新的
    // 所以不能 return this
    return new mpromise((resolve, reject) => {
      if(this.promiseState === 'fulfilled') {
        let res = onResolve(this.promiseResult)
        if(res instanceof mpromise) { // 如果返回的还是一个 promise,则需要怎么处理

        } else {

        }
      }
      if(this.promiseState === 'rejected') {
        let res = onRejected(this.promiseResult)
      }
      if(this.promiseState === 'pending') {
        onResolve && this.resolveQueue.push(onResolve)
        onRejected && this.rejectQueue.push(onRejected)
      }
    })
    
  }

然后 我们要给新的then返回的promise加上结果和改变状态

如何获取结果并赋值给新的 promise promiseResult 呢?

onRejected(this.promiseResult) 便是then 中回调函数的执行,可以获取到结果
调用新promise 中 reject() 既可以改变状态也可以改变 promiseResult 
then(onResolve, onRejected) { // 添加任务队列
    // 因为状态只能单向改变,如果之前resolve了,后面then中throw抛出异常则无法改变状态
    // 另外任务队列也不是最新的
    // 所以不能 return this
    return new mpromise((resolve, reject) => {
      if(this.promiseState === 'fulfilled') {
        setTimeout(() => {
          try {
            let res = onResolve(this.promiseResult)
            if(res instanceof mpromise) { // 如果返回的还是一个 promise,则需要怎么处理
              res.then(res => {resolve(res)}, err => {reject(err)})
            } else {
              resolve(res) // 改变新的 promise 里面的状态
            }
          } catch(err) {
            reject(err)
          }
        })
      }
      if(this.promiseState === 'rejected') {
        let res = onRejected(this.promiseResult)
        if(res instanceof mpromise) { // 如果返回的还是一个 promise,则需要怎么处理
          res.then(res => {resolve(res)}, err => {reject(err)})
        } else {
          reject(res) // 改变新的 promise 里面的状态
        }
      }
      if(this.promiseState === 'pending') {
        onResolve && this.resolveQueue.push(onResolve)
        onRejected && this.rejectQueue.push(onRejected)
      }
    })
    
  }

 8、异步修改状态 then 方法结果返回(Promise,return,throw)

因为 同步的时候直接 走 fulfilled 和 rejected 条件里的方法(改变了状态和结果)

这时如果变成异步的话,我们会发现then 返回的新的promise是状态没改,结果为undefind

 

 所以我们接下来处理一下 pending 的时候的情况,其实和上面两种情况差不多,

最后处理成

if(this.promiseState === 'pending') {
        onResolve && this.resolveQueue.push(function() {
          let res = onResolve(this.promiseResult)
          this.handleState(res, resolve, reject)
        })
        onRejected && this.rejectQueue.push(function() {
          let res = onRejected(this.PromiseResult)
          handleState(res,resolve,reject)
        })
      }

 

封装代码得

then(onResolve, onRejected) { // 添加任务队列
    // 因为状态只能单向改变,如果之前resolve了,后面then中throw抛出异常则无法改变状态
    // 另外任务队列也不是最新的
    // 所以不能 return this
    return new mpromise((resolve, reject) => {
      if(this.promiseState === 'fulfilled') {
        setTimeout(() => {
          let res = onResolve(this.promiseResult)
          this.handleState(res, resolve, reject)
        })
      }
      if(this.promiseState === 'rejected') {
        let res = onRejected(this.promiseResult)
        this.handleState(res, resolve, reject)
      }
      if(this.promiseState === 'pending') {
        onResolve && this.resolveQueue.push(function() {
          let res = onResolve(this.promiseResult)
          this.handleState(res, resolve, reject)
        })
        onRejected && this.rejectQueue.push(function() {
          let res = onRejected(this.PromiseResult)
          handleState(res,resolve,reject)
        })
      }
    })
    
  }

  handleState(res,resolve,reject) {
    if (res instanceof mPromise) {
      // 如果返回的是一个promise 
      // 则调用 then获取这个 promise的 PromiseResult作为目前promie的 PromiseResult
      res.then(res => {
        // 调用 resolve 修改 PromiseResult
        resolve(res)
      }, err => {
        reject(err)
      })
    } else {
      resolve(res) // 这里有问题,并不是每次状态都是改成 fulfilled,后面再调整调整
    }
  }

 

9、catch 和 异常穿透 的实现

catch 其实在 then 中就已经实现了

catch(onRejected) {
    return this.then(undefined, onRejected)
  }

穿透的原理:

如果 onRejected 不传则抛出 err

 

 

 相当于在then 中抛出错误一层一层传下去

 

 

 到最下层 catch其实也是调用 then ,和其回调 reason => {console.warn(reason)} 的执行

 

resolve 和 reject 的实现
mpromise.resolve = function() {
  return new mpromise((resolve, reject) => {
    if (val instanceof mPromise) {
      // 如果返回的是一个promise 
      // 则调用 then获取这个 promise的 PromiseResult作为目前promie的 PromiseResult
      val.then(res => {
        // 调用 resolve 修改 PromiseResult
        resolve(res)
      }, err => {
        reject(err)
      })
    } else {
      resolve(val)
    }
  })
}

mpromise.reject = function(val) {
  return new mPromise((resolve,reject) => {
      // 无论传什么都是返回 reject
    
      reject(val)
  })
}

all的实现

返回一个有结果的 promise

和every方法类似,只要 有一个是 rejected 则返回 rejected 的值,状态为 rejected 

全部都是fulfilled 则返回 fulfilled 数组的值, 状态为 fulfilled 

mpromise.all = function(arr) {
  return new mpromise((resolve, reject) => {
    let array = []
    for(let i = 0;i < arr.length; i++){
      arr[i].then(res => {
        array.push(res)
        if(arr.length == array.length) {
          console.log(array)
          resolve(array)
        }
      }, err => {
        reject(err)
      })
    }
  })
}

 

race 的实现

race 就是数组promise 中哪个状态先改变就 返回的promise,就使用该状态和值,

因为状态的改变是单向的,所以取到的状态是先改变状态

mpromise.race = function(promises) {
  return new mpromise((resolve, reject) => {
    for(let i = 0;i < promises.length; i++){
      promises[i].then(r => {
        resolve(r)
      },e => {
        reject(e)
      })
    }
  })
}

 

posted on 2021-12-20 12:11  京鸿一瞥  阅读(102)  评论(0)    收藏  举报