• 调用的2个后端API有数据依赖问题该如何设置请求顺序更合理?
  • 发布于 1周前
  • 66 热度
    4 评论
  • 远行客
  • 0 粉丝 33 篇博客
  •   
有 A 、B 两个 API ,其中 B 的结果需要依赖 A 的结果来组装数据(类似于 B 是用户表存了角色 ID ,界面显示的时候需要依赖 A 角色表里的角色名称),之前的做法是在onMounted里先调用 A 然后再调用 B ,其中 A 被调用后我就把结果存起来了,只用调用这一次。

现在我封装了一个分页组件,于是我不在onMounted里调用 B 了,直接watch页码和页大小有变化的时候调用 B ,但是这样会导致一个问题:就是页面一加载的时候 watch 就会生效,导致 B 比 A 先执行。但是我又不想把 A 也放在watch里,因为它的数据几乎是不会变的,类似于角色表,页面加装的时候调用一次即可,大佬们有什么思路吗?
用户评论
  • 离人未归
  • 再包一两层?把 A B 分别包成两个函数,onMounted 里面调用 C ,C 取判断如果有 A 就调用 B ,如果没有 A 就先调用 A 。这样你只需要找调用 B 的地方调用 C 即可。
  • 2024/5/13 12:21:00 [ 0 ] [ 0 ] 回复
  • 北船余音
  • 我可能会这样写:
    type Role = {
        id: string;
        name: string
    };
    
    function usePage < T > () {
        const role = ref < Role | null > (null) const loading = ref(false);
        const page = reactive({
            current: 1,
            size: 10
        });
        const uri = computed(() = >` / api / b ? page = $ {
            page.current
        } & size = $ {
            page.size
        }`);
        const {
            data,
            error,
            execute
        } = useFetch(uri, {
            immediate: false
        }).json < T > ()
    
        // 防抖避免快速点击翻页按钮发送无效请求
        const onLoadPageData = debounce(async() = >{
            try {
                loading.value = true;
                await initRole();
                await execute();
            } finally {
                loading.value = false;
            }
        },
        200)
    
        async
        function initRole() {
            if (role.value) return;
            const {
                data,
                error
            } = await useFetch("/api/a").json < Role > ();
            if (error.value) {
                /** @todo error handler */
            } else {
                role.value = data.value;
                onLoadPageData();
            }
        }
    
        initRole();
        watch(page, onLoadPageData, {
            immediate: true
        });
    
        return {
            page,
            data,
            error,
            loading,
            onLoadPageData
        }
    }


  • 2024/5/13 12:09:00 [ 0 ] [ 0 ] 回复
  • Kily
  • 个 A 接口是不是在系统中别的页面也需要用到的?就是这个角色是不是全局的,如果是这个就好办啦,直接放在入口( main.js 或者 router 钩子)请求后存 session 或 local storage ,这样你在别的页面直接取就行了。
  • 2024/5/13 12:04:00 [ 0 ] [ 0 ] 回复
  • 阳光
  • 你可以考虑在你的分页组件中引入一个状态来表示 A 是否已经加载完成。这样,在组件加载时,你可以首先检查是否已经加载了 A 的数据。如果没有,那么首先加载 A ,然后再加载 B 。

    下面是一个简单的示例代码,说明了这个思路:
    import {
        ref,
        watch,
        onMounted
    }
    from 'vue';
    
    export
    default {
            setup() {
                // 用于存储 A 的数据
                const dataA = ref(null);
                // 用于表示 A 是否已经加载完成
                const isDataALoaded = ref(false);
    
                // 模拟加载 A 的数据
                function fetchDataA() {
                    // 这里假设 fetchDataA 是异步操作
                    setTimeout(() = >{
                        // 模拟从 API 获取到的 A 的数据
                        const result =
                        /* 调用 A 的 API */
                        ;
                        // 存储 A 的数据
                        dataA.value = result;
                        // 标记 A 已加载完成
                        isDataALoaded.value = true;
                    },
                    1000); // 假设加载 A 的数据需要 1 秒钟
                }
    
                // 模拟加载 B 的数据
                function fetchDataB(page, pageSize) {
                    // 这里假设 fetchDataB 是异步操作
                    setTimeout(() = >{
                        // 只有在 A 的数据加载完成后才调用 B 的 API
                        if (isDataALoaded.value) {
                            // 这里可以使用 A 的数据来组装 B 的数据
                            const result =
                            /* 调用 B 的 API ,依赖于 A 的数据 */
                            ;
                            console.log(result);
                        } else {
                            // 如果 A 的数据尚未加载完成,则等待 A 加载完成后再调用 B 的 API
                            console.log("Waiting for A to load...");
                        }
                    },
                    500); // 假设加载 B 的数据需要 0.5 秒钟
                }
    
                // 监听页码和页大小的变化,当它们变化时调用 fetchDataB
                watch([currentPage, pageSize], ([newPage, newPageSize], [oldPage, oldPageSize]) = >{
                    fetchDataB(newPage, newPageSize);
                });
    
                // 在组件加载时,如果 A 的数据尚未加载,则先加载 A 的数据
                onMounted(() = >{
                    if (!isDataALoaded.value) {
                        fetchDataA();
                    }
                });
    
                return {
                    dataA,
                    isDataALoaded,
                };
            },
        };
    这样,无论在分页组件加载时还是在页码或页大小变化时,都会先检查 A 的数据是否已经加载完成,然后再决定是否加载 B 的数据。
  • 2024/5/13 12:00:00 [ 0 ] [ 0 ] 回复