手撕Promise系列三

74 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第16天,点击查看活动详情

题外话

这个疫情啊,真滴是服气了,居家快一个月了,居家不是办公就是做饭,脑子都快麻木了,为了活跃自己的大脑,也为了帮助大家增长知识,我给大家分享一点冷知识,嘿嘿嘿……

冷知识:你晕不晕车,跟你吃没吃饭,没有一点关系,唯一的区别就是:

你吃饭了,吐的是食物;

你没吃饭,吐的是胆汁。

所以下回谁再拿我晕车阻止我吃饭你看着,哼哼

前情回顾

前两篇手撕Promise系列,对then方法进行了简单的处理:接收返回值、异步调用、多次调用进行了处理,关于then的处理其实还有很多,那就接着往下处理

链式调用

promise是可以进行链式调用的,then方法的链式调用后一个返回值实际上接收的是上一个then方法的返回值

1.then方法返回的是一个promise对象才能进行链式调用。
2.new Promise一旦新建就会立即执行
3.then方法需要接收上一个then方法的返回值作为传入的参数

  1. then方法想要链式调用就需要返回的是一个promise对象
  2. 需要对上一个then方法的返回值进行保存,将保存的返回值重新重新调用。
  3. 对返回的值进行处理,如果是普通值就直接调用resolve,将这个值传递给下一个promise对象;如果是一个promise对象,我们就需要判断这个promise对象的返回值,调用不同的回调函数进行处理。

因为对返回值进行处理,成功、失败和异步处理都需要进行一遍,所以我们可以抽离出去

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

class MyPromise {
  constructor(executor) {
    executor(this.resolve, this.reject)
  }
  status = PENDING
  resp = undefined
  error = undefined
  // successCallBack = undefined
  // failCallback = undefined
  successCallBack = []
  failCallback = []
  resolve = (resp) => {
    if (this.status !== PENDING) return
    this.status = FULFILLED
    this.resp = resp
    // this.successCallBack && this.successCallBack(this.resp)
    while (this.successCallBack.length) this.successCallBack.shift()(this.resp)
  }
  reject = (error) => {
    if (this.status !== PENDING) return
    this.status = REJECTED
    this.error = error
    // this.failCallback && this.failCallback(this.error)
    while (this.failCallback.length) this.failCallback.shift()(this.error)
  }
  then(successCallBack, failCallback) {
    //1.1 then方法需要返回一个promise对象
    let promise = new MyPromise((resolve, reject) => {
      //1.2 回到函数是同步代码,而new MyPromise调用就会执行,所以将判断代码移入
      if (this.status === FULFILLED) {
        //2.1 将上一个then方法的返回值保存起来
        let successResult = successCallBack(this.resp)
        //2.2 将保存的返回值执行resolve再次返回返回值调用,在3.6中废除
        //resolve(successResult)
        //3.6 通过调用抽离的类型判断进行重新处理
        returnPromise(successResult, resolve, reject)
      } else if (this.status == REJECTED) {
        failCallback(this.error)
      } else {
        // this.successCallBack = successCallBack
        // this.failCallback = failCallback
        this.successCallBack.push(successCallBack)
        this.failCallback.push(failCallback)
      }
    })
    return promise
  }
}
//3.1 抽离一个公共的方法对promise返回值的类型进行判断处理
// result就是上一个then方法的返回值,也是需要进行判断处理的值
function returnPromise(result, resolve, reject) {
  //3.2 判断返回的result是否是MyPromise的实例,就相当于判断result是否是promise对象
  if (result instanceof MyPromise) {
    //3.4 如果是promise对象,那么就需要通过then方法判断这个result这个返回值的状态,并且调用resolve或者reject,将返回值传递给下一个promise对象
    // result.then(resp => resolve(resp), error => reject(error))
    //3.5 可以进行简写
    result.then(resolve, rejct)
  } else {
    //3.3 如果是普通类型,直接调用resolve方法,将返回值传递给下一个promise对象
    resolve(result)
  }
}

这里我们可以进行依次验证

  • 验证基础链式调用
let promise = new MyPromise((resolve, reject) => {
  resolve(1)
})

promise.then(resp => {
  console.log(resp);
  return 100
}).then(resp => {
  console.log(resp);
})

这段代码的输出结果是1 100。说明promise的第一个then方法将100成功返回出去了,第二个then方法成功接收了上一个then方法的返回值。

  • 验证链式调用返回值类型不同
let promise = new MyPromise((resolve, reject) => {
  resolve(1)
})

function other() {
  return new MyPromise((resolve,rejct) => { 
    resolve('other')
  })
}
promise.then(resp => {
  console.log(resp);
  return other()
}).then(resp => {
  console.log(resp);
})

这段代码的输出结果是1 other,说明我们对于promise对象作为返回值的处理也成功了。

结束

这一张主要介绍的就是关于then方法链式调用相关的一些处理