作为一名程序猿,经常遇到回调函数的情况,原生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已经模拟完成~