【Promise 源码学习】第十篇 - Promise.prototype.catch 和 Promise.prototype.finally 的实现
一,前言
上篇,主要实现了 Promise 的两个静态 API(类方法):Promise.resolve
和 Promise.reject
,主要涉及以下几个点:
Promise.resolve
创建并返回一个成功的 promise;Promise.reject
创建并返回一个失败的 promise;Promise.resolve
会等待异步操作完成;Promise.reject
失败会直接返回;
本篇,将实现 Promise 两个实例 API(原型方法):Promise.prototype.catch
和 Promise.prototype.finally
;
备注:catch 和 finall 是 Promise 使用中的高频 API,在面试题中被重点考察;
二,Promise.prototype.catch
.catch 方法会处理 Promise 被拒绝的情况,并返回一个失败的 promise;
实际行为与
Promise.prototyope.then(undefined,onRejected)
相同;因此,可以理解为一个只处理了 Promise 失败态的 then 方法;
备注:导致 Promise 失败的情况有:调用了reject()
或发生异常;
1,测试原生的 Promise.prototype.catch
2,原理分析
Promise.reject
将返回一个失败状态的 promise;失败的 promise 不会等待异步处理结果返回:内部调用
reject()
会直接抛出处于 PENDING 态的 promise;由于 then 函数没有传如
onRejected
回调处理,将继续到下一个 then 处理;所以,失败状态的 promise 就会进入到 catch 方法中;
3,功能实现
使用相同代码测试,由于尚未实现原型方法 Promise.prototype.catch
,所以会报错;
在 Promise 类中,添加原型方法 catch():
测试效果与原生 Promise 一致,直接返回 PENDING 态 Promise:
4,捕获机制
在
try...catch...
中抛出的错误,会被最近的一个catch
捕获到,并且不会继续向上冒泡,除非在 catch 中继续 throw 向外部抛出错误;在 Promise 中抛出的错误,由于被
Promise.prototype.catch
捕获后,返回的仍是一个 promise 对象,因此能够被链式调用,所以,错误会一直传递到最外层;但是,如果 Promise 抛出错误,但没有使用
catch()
方法指定错误处理的回调函数,那么,抛出的错误将不会继续向外层代码传递,即:不会有任何反应;
三,Promise.prototype.finally
1,测试原生的 Promise.prototype.finally
1,成功态 Promise 的 finally
分析:
finally 方法会等待 Promise 中的异步操作执行完成;
Promise 成功时,finally 方法会被执行;(成功失败都执行);
finally 执行完成后,可以继续 .then,说明内部返回的是 promise;
Promise 成功时,resolve 的内容,将通过 finally 继续透传至下一个 then;
备注: finally 中不能获取到数据 data;
2,失败态 Promise 的 finally
分析:
Promise 失败时,finally 方法也会被执行;(成功失败都执行)
Promise 失败时,reject 的内容,将通过 finally 继续向下传递;(finally 返回失败的 promise,then 没有处理失败,会进入 catch 处理)
3,成功态 Promise 的 finally 中,返回成功 Promise
4,成功态 Promise 的 finally 中,返回失败 Promise
对比 3,4 两种情况,可得出结论:
当 finally 中的 Promise 成功时,使用上一个 promise 结果返回;
当 finally 中的 Promise 失败时,使用自己的 promise 结果返回;
5,失败态 Promise 的 finally 中,返回成功 Promise
6,失败态 Promise 的 finally 中,返回失败 Promise
对比 3,4,5,6 两种情况,可得出结论:
不管 finally 之前面 promise 是成功还是失败,只要 finally 中的 Promise 成功了,就使用上一个 promise 结果作为返回;只要 finally 中的 Promise 失败了,就使用自己的 promise 结果作为返回;
2,原理分析
对以上 6 种情况进行一下总结:
finally 是 Promise 的原型方法;
finally 中不能够获取到数据 data;
finally 内部会继续返回一个 promise;
不管 finally 前的 promise 成功或失败,finally 都会被执行;
finally 方法会等待 Promise 中的异步操作执行完成;
【finally 中没有 promise 时】不管 finally 前的 promise 成功或失败,finally 执行完成后,上一个 promise 结果都会继续向下传递;
【finally 中有 promise 时】不管 finally 前的 promise 成功或失败,只要 finally 中 Promise 成功,就返回上一个 promise 结果;只要 finally 中 Promise 失败,就返回自己的 promise 结果;
3,功能实现
1,原型方法、成功失败都执行
以上代码实现了:
finally 是 Promise 的原型方法;
finally 中不能够获取到数据 data;
finally 内部会继续返回一个 promise;
不管 finally 前的 promise 成功或失败,finally 都会被执行;
2,等待 Promise 执行完成
finally 内部调用 then,最终会返回 promise,promise 的成功或失败都会执行 cb;
所以,需要等待这个 promise 执行完成;使用具有等待效果的Promise.resolve()
进行包装;(注意:Promise.reject()没有等待效果,错误会直接返回)
// todo 代码解析
以上代码实现了:
finally 方法会等待 Promise 中的异步操作执行完成;
四,结尾
本篇,主要实现了 Promise 两个实例 API(原型方法):Promise.prototype.catch
和 Promise.prototype.finally
,主要涉及以下几个点:
Promise.prototype.catch
功能测试、原理分析、源码实现;Promise.prototype.finally
功能测试、原理分析、源码实现;
下一篇,继续实现 Promise 的核心静态 API(类方法):Promise.all
;
评论