1、實現(xiàn)Promise的核心功能 2、判斷下當執(zhí)行器里面時異步代碼時的回調(diào)函數(shù)調(diào)用情況 3、then方法多次調(diào)用的情況 4、then方法的鏈式調(diào)用,以及如何把then方法的返回值傳遞到下一個then方法中,再判斷返回值是普通值還是peomise對象進而進一步處理 5、判斷then方法返回的對象是否和該then方法的promise對象是否相同 6、捕獲錯誤:執(zhí)行器中捕獲,成功、失敗、等待下回調(diào)函數(shù)中捕獲錯誤 7、then方法的參數(shù)變成可傳參數(shù) 8、Prmomise.all()方法 9、Prmomise.resolve() 方法 10、finally方法 11、catch方法
// 定義好MyPromise的三種狀態(tài),用三個常量來接收
const PENDING = 'pending' // 等待
const FULFILLED = 'fulfilled' // 成功
const REJECTED = 'rejected' // 失敗
class MyPromise {
// MyPromise接收一個參數(shù),這個參數(shù)是構(gòu)造器函數(shù),并且在創(chuàng)建MyPromise的實例對象時,這個構(gòu)造器函數(shù)會立即執(zhí)行
constructor(executor) {
// 構(gòu)造器函數(shù)接受兩個參數(shù):resolve、reject這兩個方法
// 捕獲執(zhí)行器錯誤
try {
executor(this.resolve, this.reject)
} catch (e) {
this.reject(e)
}
}
// MyPromise 有三種狀態(tài) 分別是:pending、fulfilled、rejected,一開始是pending狀態(tài)
status = PENDING
value = undefined // resolve傳遞的值
reason = undefined// reject傳遞的錯誤信息
// successCallBack = undefined
successCallBack = [] // then方法多次調(diào)用時且執(zhí)行器里面是異步時需將then方法里面的回調(diào)函數(shù)依此存儲在該數(shù)組中
// failCallBack = undefined
failCallBack = [] // 同上
resolve = (val) => {
if (this.status !== PENDING) return // 如果不是pending 狀態(tài)則阻止往下執(zhí)行,因為狀態(tài)一旦改變,便不可更改
// 執(zhí)行resolve方法時 狀態(tài)status修改為fulfilled
this.status = FULFILLED
// 將成功調(diào)用傳遞的值傳給this.value保存起來方便后續(xù)使用
this.value = val
// 判斷下this.successCallBack是否存在,如果存在則調(diào)用
// this.successCallBack && this.successCallBack(this.value)
// 從this.successCallBack中一個個取出成功回調(diào)函數(shù)調(diào)用并從數(shù)組中刪除
// for (let i = this.successCallBack.length; i > 0; i--) {
// // this.successCallBack.shift()(this.value)
// this.successCallBack.shift()()
// }
while(this.successCallBack.length) this.successCallBack.shift()()
}
reject = (reason) => {
if (this.status !== PENDING) return
// 執(zhí)行resolve方法時 狀態(tài)status修改為rejected
this.status = REJECTED
// 將成功調(diào)用傳遞的值傳給this.value保存起來方便后續(xù)使用
this.reason = reason
// 同理,同上
// this.failCallBack && this.failCallBack(this.reason)
// 同上
// for (let i = this.failCallBack.length; i > 0; i--) {
// // this.failCallBack.shift()(this.reason)
// this.failCallBack.shift()()
// }
while(this.failCallBack.length) this.failCallBack.shift()()
}
then(successCallBack, failCallBack) {
/****then方法不傳遞回調(diào)函數(shù)時 */
successCallBack = successCallBack ? successCallBack : value => value
failCallBack = failCallBack ? failCallBack : reason => { throw reason }
/***then方法實現(xiàn)鏈式調(diào)用 */
// 能夠讓then方法實現(xiàn)鏈式調(diào)用,說明then方法返回的還是一個 Promise對象,我們現(xiàn)在就再創(chuàng)建個 Promise對象 promise2,并將其返回
let promise2 = new MyPromise((resolve, reject) => {
/**** then方法里面的回調(diào)函數(shù)仍需要立即執(zhí)行,所以我們將他們放在 promise2的執(zhí)行器函數(shù)中*/
// 根據(jù)status的狀態(tài)判斷該調(diào)用哪個回調(diào)函數(shù),fulfilled則調(diào)用成功回調(diào)函數(shù),rejected則調(diào)用failCallBack回調(diào)函數(shù)
if (this.status === FULFILLED) {
// then方法返回的 promise2需要執(zhí)行 resolve 方法將當前 then方法回調(diào)函數(shù)的返回值傳遞給下一個then方法的回調(diào)函數(shù)中
setTimeout(() => {
// 捕獲回調(diào)函數(shù)錯誤
try {
let x = successCallBack(this.value)
// 需要判斷下 x 是普通值還是promise對象,
// 如果是普通值直接調(diào)用resolve方法,
// 如果是 Promise對象則需要查看promise對象返回的結(jié)果
// 再根據(jù)promise對象返回的結(jié)果,決定調(diào)用resolve 還是reject
// 此時還獲取不到promise2, 因為promise2需要等到new MyPromise執(zhí)行完畢之后才會獲取到,需加個異步代碼
newPromise(promise2, x, resolve, reject) // 將then方法返回的promise對象promise2也傳遞過去用于判斷 then方法return的x是否相同
} catch(e) {
reject(e)
}
}, 0);
// resolve(x)
// 調(diào)用成功回調(diào)函數(shù),并傳遞成功時的值
//successCallBack(this.value) // then方法被多次調(diào)用時,同步情況無需處理,直接調(diào)用即可
} else if(this.status === REJECTED) {
// 調(diào)用失敗回調(diào)函數(shù),并傳遞失敗的原因
//failCallBack(this.reason) // 同上
setTimeout(() => {
try {
let x = failCallBack(this.reason)
newPromise(promise2, x, resolve, reject)
} catch(e) {
reject(e)
}
}, 0);
} else { // 當執(zhí)行器中時異步代碼時并沒有立即調(diào)用resolve 或reject,所以status狀態(tài)既不是fulfilled也不是 rejected,而是還處于pending狀態(tài)
// this.successCallBack = successCallBack
// 此時將then的回調(diào)函數(shù)存起來當status狀態(tài)改變后再去調(diào)用回調(diào)函數(shù)
// this.successCallBack.push(successCallBack)
// 捕獲錯誤
this.successCallBack.push(() =>{
setTimeout(() => {
try {
let x = successCallBack(this.value)
newPromise(promise2, x, resolve, reject)
} catch(e) {
reject(e)
}
}, 0);
})
// this.failCallBack = failCallBack
// this.failCallBack.push(failCallBack)
this.failCallBack.push(() => {
setTimeout(() => {
try {
let x = failCallBack(this.reason)
newPromise(promise2, x, resolve, reject)
} catch(e) {
reject(e)
}
}, 0);
})
}
})
return promise2;
}
/***finally 無論該Promise對象是成功還是失敗都會執(zhí)行 接受一個回調(diào)函數(shù)作為參數(shù) */
finally(callBack) {
// finally最終返回Promise對象,而then方法返回的就時Promise對象
return this.then(value => {
return MyPromise.resolve(callBack()).then(() => value);
}, reason => {
return MyPromise.resolve(callBack()).then(() => { throw reason })
})
}
/****catch方法 */
catch (failCallBack) {
return this.then(undefined, failCallBack)
}
// 靜態(tài)方法all,接受參數(shù)是一個數(shù)組
static all(arr) {
// all方法的then方法的回調(diào)返回值是一個數(shù)組,定義一個數(shù)組來接收
let result = []
let index = 0
// 返回值是一個peomise對象
return new MyPromise((resolve, reject) => {
function addData(k, v) {
result[k] = v
index++
if (index === result.length) {
resolve(result)
}
}
for(let i=0; i<arr.length; i++) {
let current = arr[i]
if(current instanceof MyPromise) {
current.then(res => {
addData(i, res)
}, reason => reject(reason))
} else {
addData(i, arr[i])
}
}
})
}
/** 靜態(tài)方法 resolve,返回值是一個Promise對象,接受一個參數(shù),當這個參數(shù)是Promise對象時
* 就將該對象作為 resolve方法的返回值,如果是個普通值,則將該值包裹在一個Promise對象中作為
* resolve方法的返回值
*/
static resolve(value) {
if (value instanceof MyPromise) return value
return new MyPromise((resolve) => resolve(value))
}
}
function newPromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('循環(huán)返回相同的peomise對象')) //加return 阻止代碼往下進行
}
if (x instanceof MyPromise) {
x.then(resolve, reject)
} else {
resolve(x)
}
}
|