本文通过fetch接口请求示例,深入解析JavaScript中异步操作“传染性”的产生机制。针对函数链式依赖导致所有调用者被迫变为异步的问题,提出了一种通过自定义fetch拦截错误并同步触发后续逻辑的解决方案。文章提供了具体的代码实现,展示如何将异步函数改造为同步形式,从而消除异步状态的传播,提升代码的可读性与执行效率。
如何解决传染性
在开发过程中,若某个函数需调用内部接口以完成其功能,且该函数又依赖于其他异步函数,这将导致整个调用链中的每个函数都被迫变为异步函数。面对这种异步状态的蔓延,我们需要寻找有效的解决策略。以下通过具体示例进行说明:
// 接口请求
async function getList() {
return await fetch('/list.json').then(res => res.json())
}
async function task1() {
return await getList()
}
async function task2() {
return await task1()
}
async function task3() {
return await task2()
}
// 执行task3。获取到了getList的返回值
console.log(task3().then(res => console.log(res)));从上述代码可以看出,由于getList函数是异步的,这导致整个调用池中的所有相关函数都随之变成了异步函数。
那么,有什么办法能让其消除此异步形式呢?
一种可行的方案是将所有函数改造成同步函数。具体做法是自定义一个fetch方法,通过拦截报错并继续调用自身的异步函数,如果返回正确值则触发其包含的下一步实现。
具体实现代码如下:
function getList() {
// 此处发送一个异步请求
return fetch('/list.json')
}
function task1() {
return getList()
}
function task2() {
return task1()
}
function task3() {
return task2()
}
/* 我们先写一个main函数 */
function main() {
const task3Run = task3()
console.log(task3Run)
}
function run(fn) {
/* 判断是否为promise函数 */
const cache = []
let i = 0
const _originalFetch = window.fetch
window.fetch = (...args) => {
/* 发送请求,且报错 */
/* 判断缓存如果存在,则交付缓存 */
if (cache[i]) {
if (cache[i].status == 'fulfillled') {
return cache[i].data
} else if (cache[i].status == 'rejected') {
throw cache[i].err
}
}
const result = {
status: 'pending',
data: null,
err: null
}
cache[i++] = result
const prom = _originalFetch(...args)
.then(res => res.json())
.then((resolve)=> {
result.status = 'fulfillled'
result.data = resolve
}, (inject) => {
result.status = 'rejected'
result.err = inject
})
// 报错
throw prom
}
try {
fn()
} catch (err) {
if (err instanceof Promise) {
const reRun = () => {
i = 0;
fn()
}
err.then(reRun, reRun)
}
}
}
run(main)以上就是以fetch为例详解如何消除js异步的传染性的详细内容,更多关于fetch消除js异步传染性的资料请关注本站其它相关文章!