Promise源码分析分享

1、什么是Promise?

        Promise是ECMAscript 6原生提供的一个对象,用来传递异步操作的消息

2、Promise的基础用法

new Promise((resovle, rejcet) => {
  resovle('first resolve')
}).then(res => {
  console.log('first then:', res)
  return 'first then'
}).then(res => {
  console.log('second then', res)
  return new Promise((resolve, rejcet) => {
    rejcet('second new Promise reject')
  })
}).then(()=> {

}, err => {
  console.log('last then reject: ', err)
})

// 或者使用catch 去处理reject
new Promise((resovle, rejcet) => {
  resovle('first resolve')
}).then(res => {
  console.log('first then:', res)
  return 'first then'
}).then(res => {
  console.log('second then', res)
  return new Promise((resolve, rejcet) => {
    rejcet('second new Promise reject')
  })
}).catch(err => {
  console.log('last then reject: ', err)
})

3、Promise/A+规范(参考链接)总结

  1.  Promise有三种状态,pending、fullfilled、rejected
  2. Promise的初始状态是pending,如果Promise的状态是pending,那么这个promise可能转换到fullfilled或者rejected, 如果promise的状态是fullfilled或者rejected, 那个这个promise的状态是不可以改变的
  3. 要有then方法(thenable),通过then方法可以获取成功的value以及失败的reason
  4. then方法接受两个参数 onFullfilled和onRejected,这两个参数如果存在,一定是函数,如果不是函数那么就要忽略。
  5. 在then方法执行的时候,如果状态为fullfilled那么执行onFullfilled方法, 如果状态为rejected,那么执行onRejected方法
  6. then方法返回的是一个Promise

4、代码实现

        首先我们分析一下Promise, Promsie是可以new的,所以Promise是个Function或者Class,在实例化Promise的时候,构造函数传如的是一个执行器,有then方法,then方法有两个入参,分别是成功的回调和失败的回调

现在我们要实现下面的Promise用法

new MyPromise((resolve, reject) => {
  resolve(1)
}).then(res => {
  console.log(res)
})

实现代码

(1)设定三种状态

const FULLFILLED = 'fullfilled',
  PNEDING = 'pending',
  REJECTED = 'rejected'

 (2)写Promise的构造函数:

        promise的初始状态为Pending,value接受成功值,reason接受失败值,然后顶一个resolve方法,resolve的作用是改变promise状态以及value值;定义reject方法,rejcet方法的作用是改变promise的状态以及reason值

class MyPromise {
  constructor(exector) {
    this.state = PNEDING
    this.value
    this.reason
    this.onFullfilledCallbacks = []
    this.onRejectedCallbacks = []
    let resolve = (value) => {
      if (this.state === PNEDING) {
        this.value = value
        this.state = FULLFILLED
      }
    }
    let reject = (reason) => {
      if (this.state === PNEDING) {
        this.reason = reason
        this.state = REJECTED
      }
    }
    exector(resolve, reject)
  }
  
}

(3)写then方法

then(onFullfilled, onRejceted) {
    if (this.state === FULLFILLED) {
      onFullfilled(this.value)
    }
    if (this.state === REJECTED) {
      x = onRejceted(this.reason)
    }
  }

这样我们的ProiseV0.0.0.0.0.0.1就写好了:》

但是这个promise太简单了,处理不了异步的情况例如我们在settimeout之后进行resolve,在then方法中就拿不到resolve的值,因为在执行then方法的时候,promise的状态是pending,所以现有的then方法判断不到

new MyPromise((resolve, reject) => {
  setTimeout(() => {
    resolve(1)
  }, 1000);
}).then(res => {
  console.log(res)
})

我们要进行改造,在构造函数中增加onRejected, onFullfilled回调集合;回调集合对then方法进行改造判断Pending状态,增加

constructor(exector) {
    this.state = PNEDING
    this.value
    this.reason
    this.onFullfilledCallbacks = []
    this.onRejectedCallbacks = []
    let resolve = (value) => {
      if (this.state === PNEDING) {
        this.value = value
        this.state = FULLFILLED
        this.onFullfilledCallbacks.forEach(fn => fn())
      }
    }
    let reject = (reason) => {
      if (this.state === PNEDING) {
        this.reason = reason
        this.state = REJECTED
        this.onRejectedCallbacks.forEach(fn => fn())
      }
    }
     exector(resolve, reject)

  }
then(onFullfilled, onRejceted) {
      if (this.state === FULLFILLED) {
        onFullfilled(this.value)
        resolvePromise(p2, x, resolve, rejcet)
      }
      if (this.state === REJECTED) {
       onRejceted(this.reason)
        resolvePromise(p2, x, resolve, rejcet)
      }
      if (this.state === PNEDING) {
        this.onFullfilledCallbacks.push(() => {
          onFullfilled(this.value)
        })
        this.onRejectedCallbacks.push(() => {
          onRejceted(this.reason)
        })
      }
    return p2
  }

在pending的时候我们收集onFullfilled和onReject函数,然后在resolve或者reject方法执行的时候,对收集的方法进项执行

但是现在的Promise是不能链式调用的, 所以接下来我偷懒。(其实自己想想,就是then方法会返回一个promise,并且执行这个promise的resolve,或者是reject,并且把then方法上一次执行的返回值,放到下一次resolve中,因为我们不能确定then的回调返回的是普通值还是promise, 所以我们要进行递归,直到返回值是一个普通值为止)

then(onFullfilled, onRejceted) {
    let x
    let p2 = new MyPromise((resolve ,rejcet) => {
      if (this.state === FULLFILLED) {
        setTimeout(() => {
          x = onFullfilled(this.value)
          resolvePromise(p2, x, resolve, rejcet)
        }, 0)
      }
      if (this.state === REJECTED) {
        setTimeout(() => {
          x = onRejceted(this.reason)
          resolvePromise(p2, x, resolve, rejcet)
        }, 0);
      }
      if (this.state === PNEDING) {
        this.onFullfilledCallbacks.push(() => {
          setTimeout(() => {
            x = onFullfilled(this.value)
            resolvePromise(p2, x, resolve, rejcet)
          }, 0);
        })
        this.onRejectedCallbacks.push(() => {
          onRejceted(this.reason)
        })
      }
    })
    return p2
  }

我们用resolvePromise方法处理返回值

function resolvePromise(p2, x, resolve, reject) {
  if (p2 === x) throw new Error('...!')
  // 如果满足这个条件我们就认为这是一个promise
  if(typeof x === 'object' && x !== null || typeof x === 'funciton') {
    if (x.then && typeof x.then === 'function') {
      let then = x.then
      then.call(x, y => {
        resolve(y)
      }, err => {
        reject(err)
      })
    } else {
      resolve(x)
    }
  } else {
    // 啊!!! 我是一个普通值 int sting number boolean
    resolve(x)
  }
}

这样一个简易的Promise就写好了,当然中间还有好多细节,后续会更新完整版谢谢!!:)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值