彻底掌握 Promise - 原生 Promise.catch 的实现(七)
前言
在之前的文章中我们实现了简易版本的 Promise 以及它的大部分原生方法
提示:以下是本篇文章正文内容,下面案例可供参考
Promise.catch 方法实现起来比较容易理解,所以本文中的描述可能较少
Promise.catch 的实现
- 在 Promise 内部使用 static 关键字定义一个静态方法
- catch 方法接收一个失败的函数作为参数
- 创建一个 Promise 对象,调用失败的 reject 方法,
- 给 then 方法接收的失败函数传入 catch 方法的参数
具体实现:
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class iPromise {
constructor(callback) {
// 使用 try,catch 的方式进行函数执行的异常捕获, 防止代码的阻塞
try {
callback(this.resolve, this.reject)
} catch (error) {
this.reject(error)
}
}
value = null // 成功的值
status = PENDING // Promise 的状态默认为 pedding
reason = null // 失败的值
fulfilledList = [] // 保存成功的处理函数
rejectedList = [] // 保存失败的处理函数
resolve = (value) => {
// 如果当前 Promise 的状态不为 pedding 的话直接返回, 不执行相应代码
if (this.status != PENDING) {
return
}
// 变更状态, 保存 resolve 中传入的值
this.status = FULFILLED
this.value = value
// 使用 while 循环, 以保存成功函数的数组长度为终止条件, 使用数组的 shift 方法每次获取数组的第一个值进行执行
while (this.fulfilledList.length) {
this.fulfilledList.shift()()
}
}
reject = (reason) => {
// 如果当前 Promise 的状态不为 pedding 的话直接返回, 不执行相应代码
if (this.status != PENDING) {
return
}
// 变更状态, 保存 resolve 中传入的值
this.status = REJECTED
this.reason = reason
// 使用 while 循环, 以保存成功函数的数组长度为终止条件, 使用数组的 shift 方法每次获取数组的第一个值进行执行
while (this.rejectedList.length) {
this.rejectedList.shift()()
}
}
then(successCallback, errorCallback) {
// 如果 then 方法中没有成功 / 失败的回调函数的话, 让 Promise 的值一直被传递下去, 直到最后一个then 方法, 或者then 方法中有传入回调函数
successCallback = successCallback ? successCallback : value => value
errorCallback = errorCallback ? errorCallback : reason => reason
// 返回一个 Promise 对象, 让 Promise 可以链式调用
return new iPromise((resolve, reject) => {
// 根据 Promise 不同的状态, 执行不同的处理函数
if (this.status == FULFILLED) {
// 增加一个 setTimeout 的原因是把当前任务放到下一个宏任务里去执行
// 因为处理异步可能会有问题
setTimeout(() => {
// 使用 try /catch 来捕获函数执行中的异常情况, 不让程序执行卡住
try {
let result = successCallback(this.value)
isiPromise(result, resolve, reject)
} catch (error) {
reject(error)
}
})
} else if (this.status == REJECTED) {
setTimeout(() => {
try {
let result = errorCallback(this.reason)
isiPromise(result, resolve, reject)
} catch (error) {
reject(error)
}
})
} else {
// 如果 当前 Promise 的状态为 pedding 的话, 说明这个 promise 是异步的, 我们需要把传入的的成功 / 失败的回调函数, 保存到成功/ 失败的数组中, 等待异步返回, 执行相应的处理函数。
this.fulfilledList.push(() => {
setTimeout(() => {
try {
let result = successCallback(this.value)
isiPromise(result, resolve, reject)
} catch (error) {
reject(error)
}
})
})
this.rejectedList.push(() => {
setTimeout(() => {
try {
let result = errorCallback(this.reason)
isiPromise(result, resolve, reject)
} catch (error) {
reject(error)
}
})
})
}
})
}
/**
* catch
* @param { function } cb
* @returns promise
*
*/
static catch(cb) {
// 创建一个新的 Promise 对象
return new Promise((resolve, reject) => {
// 调用 reject 方法, 让这个 Promise 对象的状态变为失败
reject(callback)
// 在 then 方法中传入执行失败的函数
}).then(undefined, cb)
}
功能验证:
- 调用 iPromise 身上的静态方法 catch
- 传入失败的函数
由上面可以看到 catch 方法被执行了,且这个 Promise 的状态为 失败的状态
完整代码:
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class iPromise {
constructor(callback) {
// 使用 try,catch 的方式进行函数执行的异常捕获, 防止代码的阻塞
try {
callback(this.resolve, this.reject)
} catch (error) {
this.reject(error)
}
}
value = null // 成功的值
status = PENDING // Promise 的状态默认为 pedding
reason = null // 失败的值
fulfilledList = [] // 保存成功的处理函数
rejectedList = [] // 保存失败的处理函数
resolve = (value) => {
// 如果当前 Promise 的状态不为 pedding 的话直接返回, 不执行相应代码
if (this.status != PENDING) {
return
}
// 变更状态, 保存 resolve 中传入的值
this.status = FULFILLED
this.value = value
// 使用 while 循环, 以保存成功函数的数组长度为终止条件, 使用数组的 shift 方法每次获取数组的第一个值进行执行
while (this.fulfilledList.length) {
this.fulfilledList.shift()()
}
}
reject = (reason) => {
// 如果当前 Promise 的状态不为 pedding 的话直接返回, 不执行相应代码
if (this.status != PENDING) {
return
}
// 变更状态, 保存 resolve 中传入的值
this.status = REJECTED
this.reason = reason
// 使用 while 循环, 以保存成功函数的数组长度为终止条件, 使用数组的 shift 方法每次获取数组的第一个值进行执行
while (this.rejectedList.length) {
this.rejectedList.shift()()
}
}
then(successCallback, errorCallback) {
// 如果 then 方法中没有成功 / 失败的回调函数的话, 让 Promise 的值一直被传递下去, 直到最后一个then 方法, 或者then 方法中有传入回调函数
successCallback = successCallback ? successCallback : value => value
errorCallback = errorCallback ? errorCallback : reason => reason
// 返回一个 Promise 对象, 让 Promise 可以链式调用
return new iPromise((resolve, reject) => {
// 根据 Promise 不同的状态, 执行不同的处理函数
if (this.status == FULFILLED) {
// 增加一个 setTimeout 的原因是把当前任务放到下一个宏任务里去执行
// 因为处理异步可能会有问题
setTimeout(() => {
// 使用 try /catch 来捕获函数执行中的异常情况, 不让程序执行卡住
try {
let result = successCallback(this.value)
isiPromise(result, resolve, reject)
} catch (error) {
reject(error)
}
})
} else if (this.status == REJECTED) {
setTimeout(() => {
try {
let result = errorCallback(this.reason)
isiPromise(result, resolve, reject)
} catch (error) {
reject(error)
}
})
} else {
// 如果 当前 Promise 的状态为 pedding 的话, 说明这个 promise 是异步的, 我们需要把传入的的成功 / 失败的回调函数, 保存到成功/ 失败的数组中, 等待异步返回, 执行相应的处理函数。
this.fulfilledList.push(() => {
setTimeout(() => {
try {
let result = successCallback(this.value)
isiPromise(result, resolve, reject)
} catch (error) {
reject(error)
}
})
})
this.rejectedList.push(() => {
setTimeout(() => {
try {
let result = errorCallback(this.reason)
isiPromise(result, resolve, reject)
} catch (error) {
reject(error)
}
})
})
}
})
}
static all(arr) {
// 创建一个保存所有结果的list
let resultList = []
const len = arr.length
let index = 0
// 返回一个 Promise 对象,让外部可以调用 then 方法获取结果
return new iPromise((resolve, reject) => {
// 保存结果
function addData(key, value) {
resultList[key] = value
index++
if (index == len) {
resolve(resultList)
}
}
// 循环执行传入的回调函数获取返回结果
for (let i = 0; i < len; i++) {
// 判断当前项,是否为一个 Promise 对象, 如果是, 调用它的then方法获取返回结果
if (arr[i] instanceof iPromise) {
arr[i].then(value => addData(i, value), reason => reject(reason))
} else {
// 是普通对象的话, 直接返回结果
addData(i, arr[i])
}
}
})
}
/**
* 判断当前传入参数是否为 iPromise 对象
* iPromise 对象直接返回
* 普通值 生成一个新的 Promise 对象调用 新Promise 使用 resolve 方法进行返回
*/
static resolve(value) {
if (value instanceof iPromise) return value
return new iPromise((resolve, reject) => {
resolve(value)
})
}
/**
* catch
* @param { function } cb
* @returns promise
*
*/
static catch(cb) {
// 创建一个新的 Promise 对象
return new Promise((resolve, reject) => {
// 调用 reject 方法, 让这个 Promise 对象的状态变为失败
reject(callback)
// 在 then 方法中传入执行失败的函数
}).then(undefined, cb)
}
finally(callback) {
// 1. 调用当前 Promise 的 then 方法返回一个新的 Promise 对象(保证链式调用)
return this.then(
// 2. 调用 Promise 中的 resolve 方法进行返回
(value) => this.resolve(callback()).then(() => value),
(reason) =>
this.resolve(callback()).then(() => {
throw reason;
})
);
}
}
function isiPromise(result, resolve, reject) {
// 判断当前 传入的result 是否为 Promise 对象,
if (result instanceof iPromise) {
result.then(resolve, reject)
} else {
resolve(result)
}
}
总结
以上就是今天要讲的内容,本文仅仅简单介绍了 Promise.catch 的实现,自此 Promise 原生的实现也告一段落,敬请期待后续更新