作為一名程序猿,經(jīng)常遇到回調(diào)函數(shù)的情況,原生js的回調(diào)函數(shù)是一層一層的嵌套調(diào)用,而es6提供了一種新的寫法,Promise,它可以把原本的嵌套回調(diào)函數(shù)實現(xiàn)成橫向的調(diào)用,即鏈式調(diào)用。
下面看一個Promise的簡單用法:
//Promise函數(shù)接受一個函數(shù)作為參數(shù),接受的函數(shù)中的resolve和reject分別作為執(zhí)行成功和執(zhí)行失敗的函數(shù)
var promise = new Promise(function(resolve, reject){
if(/*異步執(zhí)行成功*/){
resolve()
}else{
reject()
}
})
//通過then設(shè)置之后的兩個操作
.then(function(){
//回調(diào)執(zhí)行成功的操作
},function(){
//回調(diào)執(zhí)行失敗的操作
})
接著開始模擬:
(一)模擬模擬Promise構(gòu)造函數(shù)
function _Promise(resolver){
this._status = 'pending'
this._result = ''
resolver(this.resolve.bind(this), this.reject.bind(this))
}
首先,_Promise構(gòu)造函數(shù)會接收一個函數(shù)resolver并執(zhí)行,函數(shù)中又包含resolve和reject兩個參數(shù),然后,_Promise構(gòu)造函數(shù)生成的實例有三種狀態(tài),分別是pending(初始值)、fullfilled(成功)和rejected(失?。矣蓀ending變?yōu)槌晒蛘呤『鬆顟B(tài)不可逆。
(二)實現(xiàn)resolve和reject函數(shù)
_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函數(shù)執(zhí)行的時候會先判斷狀態(tài),如果是pending則執(zhí)行,且將狀態(tài)變?yōu)閒ullfilled或者rejected,并將resolve/reject函數(shù)中參數(shù)傳遞給_result,以便then函數(shù)調(diào)用時使用。
(三)模擬then函數(shù)
_Promise.prototype.then = function(isResolve, isReject){
if(this._status === 'fullfilled'){
var _isPromise = isResolve(this._result) //執(zhí)行成功函數(shù)
if(_isPromise instanceof _Promise){ //如果執(zhí)行成功函數(shù)后返回的是_Promise實例,則返回這個實例
return _Promise
}
return this
}else if(this._status === 'rejected' && arguments[1]){ //只有狀態(tài)是失敗且有第二個參數(shù)才執(zhí)行
var err = new TypeError(this._result)
var _isPromise = isReject(err) //將錯誤信息傳遞給失敗函數(shù)
if(_isPromise instanceof _Promise){ //如果執(zhí)行失敗函數(shù)后返回的是_Promise實例,則返回這個實例
return _Promise
}
return this
}
}
因為有可能存在鏈式調(diào)用,所以執(zhí)行then函數(shù)的返回值需要判斷,如果isResolve或者isReject函數(shù)返回的是一個新的_Promise實例,則返回這個實例,否則返回當前實例
(四)模擬catch函數(shù)
//catch函數(shù)與reject函數(shù)十分類似
_Promise.prototype.catch = function(isReject){
if(this._status === 'rejected'){
var _isPromise = isReject(this._result)
if(_isPromise instanceof _Promise){
return _Promise
}
return this
}
}
至此,Promise已經(jīng)模擬完成~