手寫Promise實作程序
- 1、實作Promise的核心功能
- 2、判斷下當執行器里面時異步代碼時的回呼函式呼叫情況
- 3、then方法多次呼叫的情況
- 4、then方法的鏈式呼叫,以及如何把then方法的回傳值傳遞到下一個then方法中,再判斷回傳值是普通值還是peomise物件進而進一步處理
- 5、判斷then方法回傳的物件是否和該then方法的promise物件是否相同
- 6、捕獲錯誤:執行器中捕獲,成功、失敗、等待下回呼函式中捕獲錯誤
- 7、then方法的引數變成可傳引數
- 8、Prmomise.all()方法
- 9、Prmomise.resolve() 方法
- 10、finally方法
- 11、catch方法
// 定義好MyPromise的三種狀態,用三個常量來接收
const PENDING = 'pending' // 等待
const FULFILLED = 'fulfilled' // 成功
const REJECTED = 'rejected' // 失敗
class MyPromise {
// MyPromise接收一個引數,這個引數是構造器函式,并且在創建MyPromise的實體物件時,這個構造器函式會立即執行
constructor(executor) {
// 構造器函式接受兩個引數:resolve、reject這兩個方法
// 捕獲執行器錯誤
try {
executor(this.resolve, this.reject)
} catch (e) {
this.reject(e)
}
}
// MyPromise 有三種狀態 分別是:pending、fulfilled、rejected,一開始是pending狀態
status = PENDING
value = https://www.cnblogs.com/my-place/p/undefined // resolve傳遞的值
reason = undefined// reject傳遞的錯誤資訊
// successCallBack = undefined
successCallBack = [] // then方法多次呼叫時且執行器里面是異步時需將then方法里面的回呼函式依此存盤在該陣列中
// failCallBack = undefined
failCallBack = [] // 同上
resolve = (val) => {
if (this.status !== PENDING) return // 如果不是pending 狀態則阻止往下執行,因為狀態一旦改變,便不可更改
// 執行resolve方法時 狀態status修改為fulfilled
this.status = FULFILLED
// 將成功呼叫傳遞的值傳給this.value保存起來方便后續使用
this.value = val
// 判斷下this.successCallBack是否存在,如果存在則呼叫
// this.successCallBack && this.successCallBack(this.value)
// 從this.successCallBack中一個個取出成功回呼函式呼叫并從陣列中洗掉
// 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
// 執行resolve方法時 狀態status修改為rejected
this.status = REJECTED
// 將成功呼叫傳遞的值傳給this.value保存起來方便后續使用
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方法不傳遞回呼函式時 */
successCallBack = successCallBack ? successCallBack : value => value
failCallBack = failCallBack ? failCallBack : reason => { throw reason }
/***then方法實作鏈式呼叫 */
// 能夠讓then方法實作鏈式呼叫,說明then方法回傳的還是一個 Promise物件,我們現在就再創建個 Promise物件 promise2,并將其回傳
let promise2 = new MyPromise((resolve, reject) => {
/**** then方法里面的回呼函式仍需要立即執行,所以我們將他們放在 promise2的執行器函式中*/
// 根據status的狀態判斷該呼叫哪個回呼函式,fulfilled則呼叫成功回呼函式,rejected則呼叫failCallBack回呼函式
if (this.status === FULFILLED) {
// then方法回傳的 promise2需要執行 resolve 方法將當前 then方法回呼函式的回傳值傳遞給下一個then方法的回呼函式中
setTimeout(() => {
// 捕獲回呼函式錯誤
try {
let x = successCallBack(this.value)
// 需要判斷下 x 是普通值還是promise物件,
// 如果是普通值直接呼叫resolve方法,
// 如果是 Promise物件則需要查看promise物件回傳的結果
// 再根據promise物件回傳的結果,決定呼叫resolve 還是reject
// 此時還獲取不到promise2, 因為promise2需要等到new MyPromise執行完畢之后才會獲取到,需加個異步代碼
newPromise(promise2, x, resolve, reject) // 將then方法回傳的promise物件promise2也傳遞過去用于判斷 then方法return的x是否相同
} catch(e) {
reject(e)
}
}, 0);
// resolve(x)
// 呼叫成功回呼函式,并傳遞成功時的值
//successCallBack(this.value) // then方法被多次呼叫時,同步情況無需處理,直接呼叫即可
} else if(this.status === REJECTED) {
// 呼叫失敗回呼函式,并傳遞失敗的原因
//failCallBack(this.reason) // 同上
setTimeout(() => {
try {
let x = failCallBack(this.reason)
newPromise(promise2, x, resolve, reject)
} catch(e) {
reject(e)
}
}, 0);
} else { // 當執行器中時異步代碼時并沒有立即呼叫resolve 或reject,所以status狀態既不是fulfilled也不是 rejected,而是還處于pending狀態
// this.successCallBack = successCallBack
// 此時將then的回呼函式存起來當status狀態改變后再去呼叫回呼函式
// 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物件是成功還是失敗都會執行 接受一個回呼函式作為引數 */
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)
}
// 靜態方法all,接受引數是一個陣列
static all(arr) {
// all方法的then方法的回呼回傳值是一個陣列,定義一個陣列來接收
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 {
addData(i, res)
}, reason => reject(reason))
} else {
addData(i, arr[i])
}
}
})
}
/** 靜態方法 resolve,回傳值是一個Promise物件,接受一個引數,當這個引數是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('回圈回傳相同的peomise物件')) //加return 阻止代碼往下進行
}
if (x instanceof MyPromise) {
x.then(resolve, reject)
} else {
resolve(x)
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/256660.html
標籤:JavaScript
上一篇:幸福西餅:靜態頁面制作專案總結
