实现自己的Promise-2-链式操作

首先我们看下链式调用的例子

function testP1(){
  return new MyPromise((resolve,reject)=>{
    setTimeout(()=>{
      resolve('p1')
    },2000)
  })
}
function testP2(){
  return new MyPromise((resolve,reject)=>{
    setTimeout(()=>{
      resolve('p2')
    },2000)
  })
}
testP1().then((res)=>{
  console.log(res);
  return testP2()
}).then((res)=>{
  console.log(res);
})

可以看到我们在传入给第一个promise的then函数的回调函数中、返回了一个promise,同时又执行了一个then函数。
也就是说
我们的then函数最终返回了一个promise。那么。我们是不是让我们的then函数变成

then((onFulfilled,onRejected){
    return onFulfilled
}

就好了?
如果我们只是想实现这样的结构。当然是没有问题的

function test1(){
  return {
    a(){
      console.log('a');
    }
  }
}

function test2(){
  return {
    test(fn){
      return fn()
    }
  }
}

test2().test(()=>{
  return test1()
})
.a() // a

最终输出a

但是可惜的是。
1、我们的promise是异步的 我们的then函数现在是

  then(onFulfilled,onRejected){
    if(this.state==='fulfilled'){
      onFulfilled(this.value)
    }
    if(this.state==='rejected'){
      onRejected(this.reason)
    }
    if(this.state==='pedding'){
      this.onFulfilledCallbacks.push(onFulfilled)
      this.onRejectedCallbacks.push(onRejected)
    }
  }

这个样子的

2、如果不返回promise呢?

第一个问题决定了,我们的then函数的回调函数会在return之后执行
也就是说如果我们要按照上面的写法得话,那么就是

  then(onFulfilled, onRejected) {
    let promise2
    if (this.state === 'fulfilled') {
      promise2 = onFulfilled(this.value)
    }
    if (this.state === 'rejected') {
      promise2 = onRejected(this.reason)
    }
    if (this.state === 'pedding') {
      this.onFulfilledCallbacks.push(onFulfilled)
      this.onRejectedCallbacks.push(onRejected)
    }
    return promise2
  }

那么问题就很明显了
我们没有办法去处理pedding的时候的promise2 因为他是被压入了一个栈中,在resolve之后才能执行,所以,我们的promise2 在大部分情况下都是 undefined

也就是说 我们不能直接返回 return 的 nextPromise
注意、我这里没有说promise2 而是nextPromise 为什么要进行区分?因为promise2是我们定义在class Promise的then函数里面的,而nextPromise是未知的。
从而我们进而得出了一个问题、无法直接返回nextPromise 那么我们nextThen怎么进行处理呢?

在代码

function testP1() {
  return new MyPromise((resolve, reject) => {
    setTimeout(() => {
      resolve('p1')
    }, 2000)
  })
}

function testP2() {
  return new MyPromise((resolve, reject) => {
    setTimeout(() => {
      resolve('p2')
    }, 2000)
  })
}
testP1().then((res) => {
  console.log(res);
  return testP2()
}).then((res) => {
  console.log(res);
})

中、我们的第二个then函数到底是怎么回事?到底是谁在执行?
那么我们就有了两个问题
1、返回什么
2、怎么处理then函数

先来处理第一个
首先,必须是返回一个promise 因为promise才有then函数、得出代码

  then(onFulfilled, onRejected) {
    let promise2 = new MyPromise((resolve, reject) => {

    })
    if (this.state === 'fulfilled') {
      onFulfilled(this.value)
    }
    if (this.state === 'rejected') {
      onRejected(this.reason)
    }
    if (this.state === 'pedding') {
      this.onFulfilledCallbacks.push(onFulfilled)
      this.onRejectedCallbacks.push(onRejected)
    }
    return promise2
  }

那么这个函数的exector是什么呢?
此外 我们应该注意到一个问题、then函数
then函数不是在延迟之后才执行的,而是立刻执行的,但是他把then函数的参数—某个回调函数压入了一个函数栈中,等到时机进行执行。
我们可以进行一次debugger
在这里插入图片描述

观察此图
可以发现
1、输出了一个 then 标记
2、回调函数栈 onFulfilledCallbacks 跟 onRejectedCallbacks 中存在函数了
3、promise2中空空如也

那么我们执行下一操作
在这里插入图片描述

可以发现又执行了一个 then函数 进行了输出 且此时没有输出 p1 也就是说第一个then函数中的回调函数没有执行

为了进行区分 我们对我们的测试代码进行部分修改

function testP1() {
  return new MyPromise((resolve, reject) => {
    setTimeout(() => {
      resolve('p1')
    }, 2000)
  })
}

function testP2() {
  return new MyPromise((resolve, reject) => {
    setTimeout(() => {
      resolve('p2')
    }, 2000)
  })
}
testP1().then((res1) => {
  console.log(res1);
  return testP2()
}).then((res2) => {
  console.log(res2);
})

可以看到我们修改了我们的 then的回调函数 第一个传入的参数是res1 第二个参数是res2
重新debugger一次
在这里插入图片描述

可以看到第一步我们的函数是第一个 回调函数是res1 => {}
而点击 继续
在这里插入图片描述

变成了 res2=>{}
此时是返回的promise2

我们执行这样的操作为了证明什么呢?
为了证明
1、第二个then函数 其实是在第一个promise返回的promise2中 而不是在nextPromise中
2、then函数的执行是同步的 也就是说 ,当我们一个链式操作写完的时候 所有的then函数会按照流式执行,而不会进入异步队列中 等到上一个then函数中的回调函数执行后 才执行下一个then函数
如图
在这里插入图片描述

所以说,此时nextPromise的then中是没有回调函数的,也不会去执行,而nextPromise 我们以为要执行的回调函数其实是在promise2中
那么我们给出解决方案
1、在恰当的时候 执行 nextPromise的then函数
2、在nextPromise 的resolve执行的时候,控制promise2的resolve执行,从而执行promise2中then函数接受到得回调函数

对于第一个问题
必然是在 上一个promise的then函数的回调函数执行之后才执行 为什么?因为nextPromise就是前一个then函数的回调函数的返回值~~ 所以 必然是在之后执行
对于第二个问题
当nextPromise的resolve执行之后,会调用 nextPromise中的then函数的第一个参数 也就是onFulfilled 所以我们可以在这里 执行promise2的resolve函数 因此我们必须把promise2的resolve函数传递给nextPromise的then函数的回调函数中或者说在这里执行

因此 对于代码

  then(onFulfilled, onRejected) {
    console.log('then');
    let promise2 = new MyPromise((resolve, reject) => {

    })
    if (this.state === 'fulfilled') {
      onFulfilled(this.value)
    }
    if (this.state === 'rejected') {
      onRejected(this.reason)
    }
    if (this.state === 'pedding') {
      this.onFulfilledCallbacks.push(onFulfilled)
      this.onRejectedCallbacks.push(onRejected)
    }
    return promise2
  }

应该改成

  then(onFulfilled, onRejected) {
    console.log('then');
    let promise2 = new MyPromise((resolve, reject) => {
      if (this.state === 'fulfilled') {
        onFulfilled(this.value)
      }
      if (this.state === 'rejected') {
        onRejected(this.reason)
      }
      if (this.state === 'pedding') {
        this.onFulfilledCallbacks.push(onFulfilled)
        this.onRejectedCallbacks.push(onRejected)
      }
    })
    return promise2
  }

那么我们再来执行下一步操作
如何在第一个then之后的回调函数执行之后执行 nextPromise的then 这个并不难,拿到值执行就好了,给出以下的代码

then(onFulfilled, onRejected) {
    let promise2 = new MyPromise((resolve, reject) => {
      if (this.state === 'fulfilled') {
        onFulfilled(this.value)
      }
      if (this.state === 'rejected') {
        onRejected(this.reason)
      }
      if (this.state === 'pedding') {
        this.onFulfilledCallbacks.push(()=>{
          let x =onFulfilled(this.value)
          if(typeof x === 'object'){
            if(typeof x.then === 'function'){
              x.then.call(x,res=>{
                resolve(res)
              })
            }
          }
        })
        this.onRejectedCallbacks.push(onRejected)
      }
    })
    return promise2
  }

我们先只观察pedding中的onFulfilledCallbacks 我们队原来的onFulfilledCallbacks进行了进一步的封装不再是单纯的执行内容了,而是先执行onFulfilledCallbacks后再执行 nextPromise的回调函数,并将resolve放入then中执行,所以在执行nextPromise的resolve的时候就会执行nextPromise的then的回调函数,从而执行promise2的resolve函数

同时对于reject也应该执行类似的操作 所以我们可以提成一个函数
resolvePromise

  then(onFulfilled, onRejected) {
    let promise2 = new MyPromise((resolve, reject) => {
      if (this.state === 'fulfilled') {
        let x =onFulfilled(this.value)
        resolvePromise(promise2,x,resolve,reject)
     
      }
      if (this.state === 'rejected') {
        
        let x =onRejected(this.reason)
        resolvePromise(promise2,x,resolve,reject)
     
      }
      if (this.state === 'pedding') {
        this.onFulfilledCallbacks.push(()=>{
          let x =onFulfilled(this.value)
          resolvePromise(promise2,x,resolve,reject)
        })
        this.onRejectedCallbacks.push(()=>{
          let x =onRejected(this.reason)
          resolvePromise(promise2,x,resolve,reject)
  
        })
      }
    })
    return promise2
  }

function resolvePromise(promise2,x,resolve,reject){
  if(typeof x === 'object'){
    if(typeof x.then === 'function'){
      x.then.call(x,res=>{
        resolve(res)
      })
    }
  }
}

同时 我们还要处理一下如果返回值不是promise的情况 在Promise中

function testP1() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('p1')
    }, 2000)
  })
}

function testP2(res) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(res+'p2')
    }, 2000)
  })
}
testP1().then((res1) => {
  console.log('res1',res1); // res1 p1
  // return testP2(res1)
  return '1'
}).then((res2) => {
  console.log('res2',res2); // res2 1
})

返回的参数会作为进行传递
所以

function resolvePromise(promise2,x,resolve,reject){
  if(typeof x === 'object'){
    if(typeof x.then === 'function'){
      x.then.call(x,res=>{
        resolve(res)
      })
    }else{
      resolve(x)
    }
  }else{
    resolve(x)
  }
}

至此 我们的链式调用就基本完成了。
当然 这个并不是很符合PromiseA+的规范~或者说也没有打算按照规范走了
因为我感觉很多写promise的实现的文章,有的时候我就会在想,他们自己在写的时候真的是知道为啥要这么做吗?当然对于大神来说肯定知道,不过看到很多的实现都是一种~好像是按照大神的代码写一遍,但是却没有什么不同,这样大神虽然懂,但是去看的时候,却很难懂,等你看懂了,就花费了很长的时间了,那么效率就很低,因为大神的代码可能涉及到了其他的东西,不是逐步递进的,看起来有的时候就会有理解上的困难qwq

最后附上我在学习的过程中参考的两个博客吧,他们写的很详细,我感觉也就没有必要再去画蛇添足了,我相信你看了我的博客以后再看他们的就会好理解很多了。

小邵带你学习Promise源代码
ES6版Promise实现,给你不一样的体验

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值