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