消除异步的传染性

  1. 异步的传染性:由于 getUser 是一个异步函数,则使用 getUser 的一系列函数都要加上 async await ,这就导致原来的纯函数变成了有副作用的函数

  2. 需要在不侵入原函数的情况下,消除异步的传染性(react 中常用这种思想

async function getUser() {
    return await fetch('https://my-json-server.typicode.com/typicode/demo/profile').then(resp => resp.json());
}

async function m1() {
    return await getUser();
}

async function m2() {
    return await m1();
}

async function m3() {
    return await m2();
}

async function main() {
    const user = await m3();
    console.log(user);
}

思路分析

  1. 由于第一次请求,没有缓存,则直接 promise 报错,捕获 promise 报错后发起下一次请求,第一次请求的结果会放到缓存中;

  2. 由于报错后会发起第二次请求,这时存在第一次的缓存,则直接取值(第一次请求的结果),函数结束;

实现

function getUser() {
    return fetch('https://my-json-server.typicode.com/typicode/demo/profile');
}

function m1() {
    return getUser();
}

function m2() {
    return m1();
}

function m3() {
    return m2();
}

function main() {
    const user = m3();
    console.log(user);
}


function run(func) {
    let cache = []; // 缓存结果
    let i = 0; // 第几次运行
    const _originFetch = window.fetch;
    window.fetch = (...args) => {
        if (cache[i]) {
            if (cache[i].status === 'fulfilled') {
                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 = _originFetch(...args)
            .then(resp => resp.json())
            .then(
                (resp) => {
                    result.status = 'fulfilled';
                    result.data = resp;
                },
                (err) => {
                    result.status = 'rejected';
                    result.err = err;
                }
            )

        // fix: 第一次运行的时候直接报错,后面捕获指定的 promise 错误重新运行
        throw prom;
    };

    try {
        func();
    } catch (err) {
        // 什么时候引发重新执行 func()
        if (err instanceof Promise) {
            const reRun = () => {
                i = 0;
                func();
            };

            // 上一次请求成功后,继续发出第二次请求
            err.then(reRun, reRun);
        }
    }
}

run(main);
打赏作者
您的打赏是我前进的动力
微信
支付宝
评论

中午好👏🏻,我是 ✍🏻   疯狂 codding 中...

粽子

这有关于前端开发的技术文档和你分享。

相信你可以在这里找到对你有用的知识和教程。

了解更多

目录

  1. 1. 消除异步的传染性
  2. 2. 思路分析
  3. 3. 实现