一i:初始化三種狀態(tài):
1;待定狀態(tài)
const PENDING = 'pending'
2:以實(shí)現(xiàn) 成功狀態(tài)
const FULFILLED = 'fulfilled'
3:失敗狀態(tài)
const REJECTED = 'rejected'
二:實(shí)現(xiàn)reject()和resolve()
/ 以構(gòu)造函數(shù)的形式實(shí)現(xiàn)
class MyPromise {
constructor(executor) {
// 利用 try/catch 捕獲錯(cuò)誤
try {
executor(this.resolve, this.reject)
} catch (error) {
this.reject(error)
}
}
// 定義 Promise 初始狀態(tài)為 PENDING
status = PENDING
// resolve 后返回的數(shù)據(jù)
data = undefined
// reject 后返回的原因
reason = undefined
// 成功
resolve = data => {
// 一旦狀態(tài)改變炸卑,就不能再變
if (this.status !== PENDING) return
// 更改狀態(tài)
this.status = FULFILLED
// 保存數(shù)據(jù)
this.data = data
}
// 失敗
reject = reason => {
// 一旦狀態(tài)改變痘番,就不能再變
if (this.status !== PENDING) return
// 更改狀態(tài)
this.status = REJECTED
// 保存原因
this.reason = reason
}
}
三:實(shí)現(xiàn)then
.then() 方法是 Promise 的核心之一巡雨,異步操作的成功或失敗版仔,都可以通過
.then() 添加的回調(diào)函數(shù)進(jìn)行處理。并且它將繼續(xù)返回一個(gè) Promise 對(duì)象馒吴,這樣可以通過多次調(diào)用
.then() 添加多個(gè)回調(diào)函數(shù)寺晌,它們會(huì)按照插入的順序執(zhí)行,形成鏈?zhǔn)秸{(diào)用(chaining)户魏。
class MyPromise {
/ resolve 的回調(diào)函數(shù)列表
successCallback = []
// reject 的回調(diào)函數(shù)列表
failureCallback = []
// 成功
resolve = data => {
// 依次調(diào)用成功回調(diào)
while (this.successCallback.length) {
this.successCallback.shift()(this.data)
}
}
// 失敗
reject = reason => {
// 依次調(diào)用失敗回調(diào)
while (this.failureCallback.length) {
this.failureCallback.shift()(this.reason)
}
}
// .then():處理 resolve 和 reject
then(onResolved = data => data /*設(shè)置默認(rèn)的成功回調(diào) */, onRejected) {
// 創(chuàng)建一個(gè)新的 Promise 并 return驶臊,以供鏈?zhǔn)秸{(diào)用
let promise = new MyPromise((resolve, reject) => {
if (this.status === FULFILLED) {
// 轉(zhuǎn)換為 異步執(zhí)行,用來獲取 新的 promise
setTimeout(() => {
try {
let value = onResolved(this.data)
// 判斷返回值是普通值還是 Promise
resolvePromise(promise, value, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
} else if (this.status === REJECTED) {
setTimeout(() => {
try {
let value = onRejected(this.reason)
resolvePromise(promise, value, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
} else {
// 將回調(diào)函數(shù)存入數(shù)組中等待被執(zhí)行
this.successCallback.push(() => {
setTimeout(() => {
try {
let value = onResolved(this.data)
resolvePromise(promise, value, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
})
// 將回調(diào)函數(shù)存入數(shù)組中等待被執(zhí)行
this.failureCallback.push(() => {
setTimeout(() => {
try {
let value = onRejected(this.reason)
resolvePromise(promise, value, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
})
}
})
return promise
}
}
第四步:實(shí)現(xiàn) .catch()
實(shí)現(xiàn) .then() 之后叼丑,.catch() 就會(huì)簡單很多关翎。事實(shí)上,.catch() 只是沒有給 fulfilled 狀態(tài)預(yù)留參數(shù)位置的 .then() 而已幢码,所以這里我們直接返回一個(gè)沒有成功回調(diào)函數(shù)的 .then() 即可笤休。
class MyPromise {
// .catch()
catch(onRejected) {
// 事實(shí)上 .catch() 只是沒有給 fulfilled 狀態(tài)預(yù)留參數(shù)位置的 .then()
return this.then(undefined, onRejected)
}
}
第五步:實(shí)現(xiàn) .finally()
有時(shí)候我們會(huì)在成功或失敗執(zhí)行相同的函數(shù),為了避免了同樣的語句需要在中各寫一次的情況症副,所以有了.finally() 方法店雅。也就是說,在 Promise 的結(jié)果無論是 fulfilled 或者是 rejected贞铣,.finally() 都會(huì)執(zhí)行指定的回調(diào)函數(shù)闹啦。但區(qū)別于 .then() 和 .catch(),.finally() 的回調(diào)函數(shù)中不接收任何參數(shù)
class MyPromise {
// .finally()
finally(callback) {
return this.then(
data => {
return MyPromise.resolve(callback().then(() => data))
},
err => {
return MyPromise.resolve(callback()).then(() => {
throw err
})
}
)
}
}
第六步:實(shí)現(xiàn) Promise.all()
Promise.all() 方法主要用于集合多個(gè) Promise 的返回結(jié)果辕坝。
class MyPromise {
// Promise.all()
static all(iterable) {
// 記錄執(zhí)行次數(shù)
let times = 0
// 保存執(zhí)行結(jié)果
let result = []
// Promise.all() 會(huì)返回一個(gè) Promise
return new MyPromise((resolve, reject) => {
// 記錄結(jié)果
function addData(key, value) {
times++
result[key] = value
times === iterable.length && resolve(result)
}
// 依次執(zhí)行窍奋,然后將結(jié)果保存到數(shù)組中
iterable.forEach((element, index) => {
// 判斷元素是否為 Promise 對(duì)象
element instanceof MyPromise
? element.then(
data => addData(index, data),
err => reject(err) // 任何一個(gè) Promise 對(duì)象的 reject 被執(zhí)行都會(huì)立即 reject()
)
: addData(index, element) // 非 promise 的元素將被直接放在返回?cái)?shù)組中
})
})
}
}
第七步:實(shí)現(xiàn) Promise.resolve(
Promise.resolve() 方法返回一個(gè)以給定值解析后的 Promise 對(duì)象。
class MyPromise {
// Promise.resolve()
static resolve(value) {
// 返回一個(gè)以給定值解析后的 Promise 對(duì)象
return value instanceof MyPromise
? value
: new MyPromise(resolve => resolve(value))
}
}
第八步:實(shí)現(xiàn) Promise.reject()
Promise.reject() 方法返回一個(gè)帶有拒絕原因的 Promise 對(duì)象酱畅。
class MyPromise {
// Promise.reject()
static reject(error) {
return new MyPromise((resolve, reject) => {
reject(error)
})
}
}