前端大全

原生JS模拟Promise实现详解

2019-03-11  本文已影响79人  yun_154192

作为一名程序猿,经常遇到回调函数的情况,原生js的回调函数是一层一层的嵌套调用,而es6提供了一种新的写法,Promise,它可以把原本的嵌套回调函数实现成横向的调用,即链式调用。
下面看一个Promise的简单用法:

//Promise函数接受一个函数作为参数,接受的函数中的resolve和reject分别作为执行成功和执行失败的函数
var promise = new Promise(function(resolve, reject){
  if(/*异步执行成功*/){
    resolve()
  }else{
    reject()  
  }
})
//通过then设置之后的两个操作
.then(function(){
  //回调执行成功的操作
},function(){
  //回调执行失败的操作
})

接着开始模拟:

(一)模拟模拟Promise构造函数

function _Promise(resolver){
  this._status = 'pending'
  this._result = ''
  resolver(this.resolve.bind(this), this.reject.bind(this))
}

首先,_Promise构造函数会接收一个函数resolver并执行,函数中又包含resolve和reject两个参数,然后,_Promise构造函数生成的实例有三种状态,分别是pending(初始值)、fullfilled(成功)和rejected(失败),且由pending变为成功或者失败后状态不可逆。

(二)实现resolve和reject函数

_Promise.prortotype.resolve = function(result){
  if(this._status === 'pending'){
    this._status = 'fullfilled'
    this._result = result
  }
}
_Promise.prototype.reject = function(result){
  if(this._status === 'pending'){
    this._status = 'rejected'
    this._result = result
  }
}

resolve和reject函数执行的时候会先判断状态,如果是pending则执行,且将状态变为fullfilled或者rejected,并将resolve/reject函数中参数传递给_result,以便then函数调用时使用。

(三)模拟then函数

_Promise.prototype.then = function(isResolve, isReject){
  if(this._status === 'fullfilled'){
    var _isPromise = isResolve(this._result)  //执行成功函数
    if(_isPromise instanceof _Promise){  //如果执行成功函数后返回的是_Promise实例,则返回这个实例
      return _Promise
    }
    return this
  }else if(this._status === 'rejected' && arguments[1]){  //只有状态是失败且有第二个参数才执行
    var err = new TypeError(this._result)
    var _isPromise = isReject(err)  //将错误信息传递给失败函数
    if(_isPromise instanceof _Promise){  //如果执行失败函数后返回的是_Promise实例,则返回这个实例
      return _Promise
    }
    return this
  } 
}

因为有可能存在链式调用,所以执行then函数的返回值需要判断,如果isResolve或者isReject函数返回的是一个新的_Promise实例,则返回这个实例,否则返回当前实例

(四)模拟catch函数

//catch函数与reject函数十分类似
_Promise.prototype.catch = function(isReject){
  if(this._status === 'rejected'){
    var _isPromise = isReject(this._result)  
    if(_isPromise instanceof _Promise){
      return _Promise
    }
    return this
  }
}

至此,Promise已经模拟完成~

上一篇下一篇

猜你喜欢

热点阅读