DEV Community

yinjialu
yinjialu

Posted on

2行代码,解决静态冲突,自动帮你取消重复的过期请求

Image description

安装

npm i --save abort-request
Enter fullscreen mode Exit fullscreen mode

使用方式

  • 避免竞态冲突,detail 总是最新值

    原始写法

    import { watch, ref, unref } from 'vue';
    
    // 请求方法
    const getDataAPI = ({ params }: { params: { id: string } }) => {
        // 发起请求
    };
    
    const id = ref();
    const detail = ref();
    
    // 调用请求方法,handleQuery 可能多次调用,detail 数据是最新的吗?
    
    const handleQuery = () => {
    
        getDataAPI({ params: { id: unref(id) } }).then((res) => {
            detail.value = res;
        });
    };
    
    watch(id, () => {
        handleQuery();
    });
    

    2行代码优化

    import { watch, ref, unref } from 'vue';
    import { createAutoAbortExpiredRequest, isAbortError } from 'abort-request';
    
    // 请求方法
    const getDataAPI = ({ params }: { params: { id: string } }) => {
        // 发起请求
    };
    
    const id = ref();
    const detail = ref();
    
    // 创建这个请求方法的自动取消版本
    const getDataAPIAutoAbort = createAutoAbortExpiredRequest(getDataAPI);
    const handleQuery = () => {
        // 使用 getDataAPIAutoAbort 替代 getDataAPI 进行调用,传参方式不变
        getDataAPIAutoAbort({ params: { id: unref(id) } }).then((res) => {
            detail.value = res;
        });
    };
    
    watch(id, () => {
        handleQuery();
    });
    
  • 避免阻塞浏览器 - 如果旧请求还未完成,就取消

    XHR 和 Fetch 都支持传入 signal 用于中止请求,可以按照当前项目的封装方式,确定传入 signal 的方法,axios 配置参考:signal: new AbortController().signal

    const getDataAPI = ({
        params,
        signal,
    }: {
        params: { id: string };
        signal?: AbortSignal;
    }) => {
        // 发起请求
    };
    
    const handleQuery = () => {
        // getDataAPIAutoAbort 可以接受一个函数作为参数,这个函数接受 signal 参数,组装好 signal 后,返回一个数组,用做请求参数
        getDataAPIAutoAbort(({ signal }) => [
            { params: { id: unref(id) }, signal },
        ]).then((res) => {
            // 当多次调用时,未完成的请求被自动取消,不会进入 then 逻辑
            detail.value = res;
        });
    };
    
  • 处理 loading 状态

    const handleQuery = () => {
        loading.value = true;
        getDataAPIAutoAbort(({ signal }) => [{ params: { id: unref(id) }, signal }])
            .then((res) => {
                // 当多次调用时,未完成的请求被自动取消,不会进入 then 逻辑
                detail.value = res;
                loading.value = false;
            })
            .catch((err) => {
                // 判断不是取消请求的错误
                if (!isAbortError(err)) {
                    loading.value = false;
                }
            });
    
        // 不能在 finally 中处理 loading 状态
    };
    

Speedy emails, satisfied customers

Postmark Image

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Discover a treasure trove of wisdom within this insightful piece, highly respected in the nurturing DEV Community enviroment. Developers, whether novice or expert, are encouraged to participate and add to our shared knowledge basin.

A simple "thank you" can illuminate someone's day. Express your appreciation in the comments section!

On DEV, sharing ideas smoothens our journey and strengthens our community ties. Learn something useful? Offering a quick thanks to the author is deeply appreciated.

Okay