1

在开发时候如果遇到一个函数需要调用内部接口才能实现其函数功能,函数又依赖其他异步函数。则就会导致每个函数都变成了异步函数。如何解决这种传染性?如下例子:

        // 接口请求
        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)

smallStone
444 声望71 粉丝

前端一枚^_-