You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何JavaScript fetch返回值赋值的数组包含响应中不存在的数据?

问题根因

  • 混用async/await与.then链式调用,外部变量赋值存在作用域歧义,同时var声明的变量存在变量提升特性,容易被同作用域下其他逻辑意外修改,这也是改为const声明后问题消失的核心原因。
  • 浏览器控制台对引用类型的打印为懒加载模式,展开数组时读取的是当前时刻的数组值而非打印时刻的快照,很容易误导开发者判断赋值结果。
  • 未对fetch响应做状态校验,fetch仅在网络异常时才会触发catch,HTTP状态码为4xx/5xx时仍会进入正常解析逻辑,若接口返回非预期格式内容会导致变量赋值异常。
  • 若使用React18+的严格模式(开发环境默认开启),组件会被重复挂载两次,componentDidMount会被调用两次,若存在实例属性共享逻辑会导致结果累加。

修复方案

  1. 统一使用async/await写法,避免和.then混用,请求结果直接赋值到内部变量,减少外部作用域依赖。
  2. 替换var声明为const/let,规避变量提升导致的作用域污染问题。
  3. 增加fetch响应状态校验,异常场景直接抛出错误走统一捕获逻辑。
  4. 使用res.json()直接解析响应体,避免手动调用JSON.parse处理text的冗余逻辑。
  5. 增加数组格式兼容,若接口异常返回非数组内容直接转为空数组。
  6. 若需要打印引用类型快照,使用console.log(JSON.parse(JSON.stringify(target)))获取打印时刻的真实值。

修复后代码示例

async componentDidMount(){ 
    await this.getGroups();
}

async getGroups(){
    try {
        const ownerID = localStorage.getItem("userID");
        // 请求Owner维度分组
        const ownerRes = await fetch(baseURI + "/api/group/forOwner/" + ownerID, {  
            method: "GET",                          
            headers: {
                "Content-Type": "application/json",
                "Authorization": "Bearer " + localStorage.getItem("auth_token")
            }
        });
        if (!ownerRes.ok) throw new Error(`Owner分组请求失败,状态码:${ownerRes.status}`);
        const groups = await ownerRes.json() || [];

        // 请求Teacher维度共享分组
        const teacherRes = await fetch(baseURI + "/api/group/forTeacher/" + ownerID, {  
            method: "GET",                          
            headers: {
                "Content-Type": "application/json",
                "Authorization": "Bearer " + localStorage.getItem("auth_token")
            }
        });
        if (!teacherRes.ok) throw new Error(`共享分组请求失败,状态码:${teacherRes.status}`);
        const sharedGroups = await teacherRes.json() || [];

        // 数组格式兼容
        const formatOwnerGroups = Array.isArray(groups) ? groups : [];
        const formatSharedGroups = Array.isArray(sharedGroups) ? sharedGroups : [];

        this.setState({
            ownerGroups: formatOwnerGroups,
            sharedGroups: formatSharedGroups
        });
    } catch (err) {
        console.error('分组请求出错:', err);
        // 异常场景重置为空
        this.setState({
            ownerGroups: [],
            sharedGroups: []
        });
    }
}

async searchGroups(){
    try {
        document.getElementsByClassName("loaderBackground")[0].style.display = "flex";
        const list = document.getElementById("groupList-Admin");
        const searchText = document.getElementsByClassName("Fit4Life-Searchbar-Admin")[0].value.trim();
        const ownerID = localStorage.getItem("userID");
        // 清空列表
        while (list.firstChild) {
            list.removeChild(list.lastChild);
        }

        // 请求Owner维度分组
        const ownerRes = await fetch(baseURI + "/api/group/forOwner/" + ownerID, {  
            method: "GET",                          
            headers: {
                "Content-Type": "application/json",
                "Authorization": "Bearer " + localStorage.getItem("auth_token")
            }
        });
        if (!ownerRes.ok) throw new Error(`Owner分组请求失败,状态码:${ownerRes.status}`);
        const groups = await ownerRes.json() || [];

        // 请求Teacher维度共享分组
        const teacherRes = await fetch(baseURI + "/api/group/forTeacher/" + ownerID, {  
            method: "GET",                          
            headers: {
                "Content-Type": "application/json",
                "Authorization": "Bearer " + localStorage.getItem("auth_token")
            }
        });
        if (!teacherRes.ok) throw new Error(`共享分组请求失败,状态码:${teacherRes.status}`);
        const sharedGroups = await teacherRes.json() || [];

        // 后续搜索逻辑...
    } catch (err) {
        console.error('搜索分组出错:', err);
    } finally {
        // 无论成功失败都隐藏加载态
        document.getElementsByClassName("loaderBackground")[0].style.display = "none";
    }
}

内容的提问来源于stack exchange,提问作者wymtowne

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 14:48:02