目的:防止异步操作在代码中传播,影响到其他部分的执行。
方案:利用try...catch
并通过缓存的方式来处理异步请求结果,从而在后续的调用中直接使用缓存的数据。
- 在函数开始时,创建一个
cache
对象,它用于存储异步请求的状态和值。初始状态为'pending'
,值为null
。 - 将原始的
window.fetch
方法保存在oldFetch
变量中,以便后面可以还原。 - 将全局的
window.fetch
方法替换为一个新的函数。在新的fetch
方法中,首先判断cache
的状态,如果已经有缓存的数据,则直接返回缓存的值。如果cache
状态为'rejected'
,则抛出缓存的错误值。 - 如果没有缓存或缓存状态为
'pending'
,则调用原fetch
方法发起请求。接着在成功
和失败
的情况下分别将结果保存到cache
中,并改变cache
的状态为'fulfilled'
或'rejected'
。 - 在捕获到结果之前,抛出了一个
p
变量,它是新的fetch
方法返回的Promise
对象。这个步骤的目的是为了在func
执行的过程中捕获到这个Promise
,以便在后续的错误处理中使用。 - 使用
try
块来执行传入的func
函数。 - 在捕获到错误时,判断错误是否是一个
Promise
对象。使用.then()
方法再次执行func
,无论是成功
还是失败
。最后,无论如何,都会通过.finally()
来还原原始的window.fetch
方法。function run(func) { const cache = { status: 'pending', value: null, } const oldFetch = window.fetch // 修改请求逻辑 window.fetch = function (...args) { // 判断是否有缓存 if (cache.status === 'fulfilled') { return cache.value } else if (cache.status === 'rejected') { throw cache.value } // 发起请求,then或catch后保存数据 const p = oldFetch(...args) .then((res) => res.json()) // 保存值到缓存,并改变状态 .then( (res) => { cache.status = 'fulfilled' cache.value = res }, (err) => { cache.status = 'rejected' cache.value = err } ) // 抛出错误,返回当前的promise throw p } try { func() } catch (err) { // 捕获到抛出的primise ,判断是否为promise if (err instanceof Promise) { // 再次执行 err.then(func, func).finally(() => { // 还原fetch window.fetch = oldFetch }) } } } run(main)