js手写系列--简易的promise

231 阅读2分钟

简单的回调函数

function sleep(fn, delay) {
  setTimeout(() => {
    fn('Hello World')
  },delay)
}

sleep( r => {
  console.log(r);
}, 1000)

Promise的产生就是为了解决的回调函数的嵌套,但其实Promise的底层实现用的也是函数的回调原理 下面我来简单实现一个Promise函数

手写简单的Promise

function MyPromise(cb) { // cb是回调函数 
  let self = this  // 保存this值,在cb的回调函数的使用
  this.status = 'PENDING' // 状态值,一开始为PENDING状态
  function onRes(value) {  // 如果执行了onRes函数, 即执行了原生Promise中的resolve
    self.value = value     //  给promise添加value属性用来传递then
    self.status = "FULFILLED"  // 此时状态为FULFILLED
    self.onFulfilled && self.onFulfilled(value)  // Promise对象上的onFulfilled方法是执行了then方法后添加的
  }
  function onRej(err) {}
  cb(onRes, onRej)
}
MyPromise.prototype.then = function(fn) {
  if (this.status === "FULFILLED") fn(this.value) // 判断状态 如果status为成功状态
  else if (this.status === "PENDING") this.onFulfilled = fn  // 如果不是的话,给实例对象上添加方法,当上面的res执行完成后
}                                                             // 该方法跟着执行

new MyPromise((resolve, reject) => {
  setTimeout(() => {
    resolve('res')
  }, 500)
}).then( r => {
  console.log(r);
})

上述代码最难理解的就是MyPromise实例对象上onFulfilled方法的添加与执行,它的值其实就是then函数传入的回调函数,这是考虑两种情况,试想当MyPromise中cb回调函数的代码执行是同步,不涉及异步操作时,此时就没有必要给MyPromise实例对象添加onFulfilled方法,而当cb函数的执行是异步时,比如上述中传入的是一个setTimeout定时器,此时,then方法的执行是先于onRes的,这时为了保证then方法传入的回调函数执行晚于onRes,就给Promise实例对象添加onFulfilled方法,在onRes函数直接执行onFulfilled,从而实现异步执行。

总结

这个实现比较关键的点就是如何把resovle接收的值传递给then的回调函数,以及状态的改变,还有就是cb函数同步与异步执行的情况。 当然这只是最基础简单版本的Promise实现,而原生Js中为了封装Promise考虑了很多的的情况,还有一些原生Api比如.all .race ...... 这次就到这里了,下次接着跟大家分享