MyPromise的簡單偽實現(xiàn)
Promise對象表示一個異步操作的最終結(jié)果看政,用來傳遞異步傳輸?shù)臄?shù)據(jù)切省。實現(xiàn)Promise之前我們需要先了解一下Promise/A+規(guī)范
規(guī)范主要有以下幾點:
- Promise有三種狀態(tài)沦泌,pending溉痢、已完成fulfilled塘揣、rejected
- Promise的狀態(tài)只能從pending轉(zhuǎn)到fullfilled或者從pending轉(zhuǎn)向rejected蜡塌,不能逆向轉(zhuǎn)換,同時fullfilled和rejected之間也不能相互轉(zhuǎn)換
- Promise必須有一個then方法勿负,而且要返回一個Promise馏艾,供then方法的鏈?zhǔn)秸{(diào)用,也就是可thenable的
- then接受倆個回調(diào)函數(shù)(resolve與reject),在相應(yīng)的狀態(tài)轉(zhuǎn)變時觸發(fā)奴愉,回調(diào)可返回Promise琅摩,等待此Promise被resolved后,繼續(xù)觸發(fā)then鏈?zhǔn)秸{(diào)用
知道這幾個重要的特點锭硼,我們就可以參考瀏覽器內(nèi)置的api來實現(xiàn)一個Promise了房资,本文使用ES6語法
- 首先,我們來看看Promise是如何使用的檀头,以及常用的一些API
let P = new Promise()
let func1 = () => {
console.log('func1')
setTimeout(() => {
P.resolve('1')
}, 1000)
return P
}
let func2 = result => {
console.log('func2', result)
setTimeout(() => {
P.reject('2')
}, 1000)
}
let func3 = result => {
console.log('func3', result)
setTimeout(() => {
P.resolve('3')
}, 1000)
}
let func4 = result => {
console.log('func4', result)
setTimeout(() => {
P.resolve('4')
}, 1000)
}
let func5 = result => {
console.log('func5', result)
}
//調(diào)用
func1().then(func2, func3).then(func3).then(func4).catch(func5)
以上就是一個Promise的基本使用轰异,通過分析上面的使用方法,我們發(fā)現(xiàn)Promise對象擁有then和catch方法暑始,同時可以鏈?zhǔn)秸{(diào)用搭独,接下來我們參照上面的案列來實現(xiàn)自己的Promise---MyPromise
- 第一步 我們創(chuàng)建一個MyPromise類,擁有then和catch方法廊镜,
calss MyPromise {
constructor(){
}
then(){
}
catch(){
}
}
- 第二步 添加狀態(tài)管理牙肝,因為有fullfiled和rejected兩種狀態(tài),那么我們就添加resolve方法和reject方法進行狀態(tài)管理
calss MyPromise {
constructor(){
}
then(){
}
catch(){
}
// fullfiled狀態(tài)的管理
resolve() {
}
// rejected狀態(tài)的管理
reject() {
}
}
- 第三步 注冊回調(diào)函數(shù)與執(zhí)行回調(diào),設(shè)定一個數(shù)組對需要執(zhí)行的方法進行暫存配椭,以及一個方法的執(zhí)行器虫溜,該執(zhí)行器依賴于resolve和reject傳入的狀態(tài)進行相應(yīng)的執(zhí)行
calss MyPromise {
constructor(){
this.callbacks = [] //回調(diào)函數(shù)的儲存容器
}
then(){
}
catch(){
}
resolve() { // fullfilled的管理
}
reject() { // rejected的管理
}
execute(){ //回調(diào)函數(shù)觸發(fā)方法
}
}
- 第四步 編寫then函數(shù)與執(zhí)行器中的邏輯
在寫then函數(shù)之前,先看看最開始Promise的調(diào)用方式 func1().then(func2,func3).then(func4).catch(fuc5)股缸,then方法接收兩個參數(shù)衡楞,一個成功回調(diào)一個失敗回調(diào),同時可以進行鏈?zhǔn)秸{(diào)用
then(onSuccess, onFail) {
this.callbacks.push({
resolve: onSuccess,
reject: onFail
})
return this //鏈?zhǔn)秸{(diào)用
}
這時候在調(diào)用func1時他會先返回Promise對象敦姻,然后再調(diào)用setTimeout里面的resolve回調(diào)并傳入?yún)?shù)瘾境,而在resolve函數(shù)中調(diào)用了執(zhí)行器execute,并且傳入了resolve這個狀態(tài)和在func1中傳入的參數(shù)替劈;
// fullfilled的管理
resolve(result) {
this.execute('resolve', result)
}
// rejected的管理
reject(result) {
this.execute('reject', result)
}
// 執(zhí)行execute函數(shù)寄雀,其實分析到了這一步就很簡單了得滤,不過是將先前傳入callbaks中的函數(shù)取出來陨献,然后執(zhí)行其中的成功回調(diào)就是了
execute(status, result) {
// 取出之前傳入的回調(diào)函數(shù)對象(包含成功和失敗回調(diào)),然后執(zhí)行
let handlerObj = this.callbacks.shift()
handlerObj[type](result)
}
整體代碼
class MyPromise {
constructor() {
this.callbacks = []
}
then(onSuccess, onFail) {
this.callbacks.push({
resolve: onSuccess,
reject: onFail
})
return this //鏈?zhǔn)秸{(diào)用
}
catch (fail) {
return this
}
resolve(result) {
this.actuator('resolve', result) // fullfilled的管理
}
reject(result) {
this.actuator('reject', result) // rejected的管理
}
// 執(zhí)行器
execute(status, result) {
// 取出之前傳入的回調(diào)函數(shù)懂更,執(zhí)行
let handlerObj = this.callbacks.shift()
handlerObj[status](result)
}
}
- 其實到了這一步眨业,Promise的基本功能then(以及回調(diào)resolve和reject)已經(jīng)實現(xiàn)了,接下來我們來實現(xiàn)catch方法沮协,catch方法就是在Promise變成rejected狀態(tài)的時候龄捡,調(diào)用執(zhí)行的回調(diào)
class MyPromise {
constructor() {
this.callbacks = [] //then的回調(diào)
this.catchcallback = null //catach的回調(diào)
}
//此處省略其他代碼...............
catch (onFail) {
this.catchcallback = onFail // 保存?zhèn)魅氲氖』卣{(diào)
return this // 用于鏈?zhǔn)秸{(diào)用
}
//此處省略其他代碼..............
// 執(zhí)行器
execute(status, result) {
if (status === 'reject' && this.catchcallback) {
this.callbacks = [] //catch方法的處理
this.catchcallback(result)
} else if (this.callbacks[0]) {
// 取出之前傳入的回調(diào)函數(shù)對象(包含成功和失敗回調(diào)),然后執(zhí)行
let handlerObj = this.callbacks.shift()
handlerObj[status](result)
}
}
}
下面來看看func1().then(func2, func3).then(func3).then(func4).catch(func5)的執(zhí)行結(jié)果吧
- 全部fullfilled狀態(tài)
- fun2為rejected狀態(tài)
至此慷暂,一個Promise的簡單偽實現(xiàn)就完成了聘殖,行文大概理清了promise的工作原理。