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

JavaScript中fetch循环内setCookie失效,Cookie名称显示undefined问题

问题

我有一段JavaScript代码,通过fetch请求API并填充表格,同时需要读写Cookie来标记获取的数据是否为最新。但遇到Cookie问题:在for循环和fetch的then回调中设置Cookie时,总是生成一个名称为undefined的Cookie,而代码中Cookie名称都是不同的字符串。我使用Chrome 126.0.6478.62 64位版本和VSCode的Live Server扩展,手动调用setCookie("a", 62, 365)可以正常工作,请问这是什么原因?

相关代码

主逻辑代码:

const project_ids = [62, 37, 43, 67, 29];
const project_name = ["a", "b", "c", "d", "e"];

for (i = 0; i < project_ids.length; i++) {
      let v_aria = document.getElementById("v-" + project_name[i]);
      let aria_collapse = document.getElementById(
        project_name[i] + "-collapse"
      );
      let aria_link = document.getElementById(project_name[i] + "-link");
      let aria_data = document.getElementById(project_name[i] + "-data");
      fetch(
        "https://<my_domain>/api/v4/projects/" +
          project_ids[i] +
          "/releases",
        {
          method: "GET",
          headers: {
            "PRIVATE-TOKEN": GITTOKEN,
          },
        }
      )
        .then((response) => response.json())
        .then((json) => {
          v_aria.innerHTML = json[0]["name"];
          //aria_collapse.innerHTML = json[0]["description"];
          let link = json[0]["_links"].self;
          aria_link.innerHTML = '<a href="'.concat(
            link,
            '" target="_blank">Prject</a>'
          );
          aria_data.innerHTML = json[0]["released_at"];
          let cookie = getCookie(project_name[i]);
          if (cookie != json[0]["name"]) {
            v_aria.classList.add("bg-warning");
            setCookie(project_name[i], json[0]["name"], 365);
          }
        })
        .catch(function (error) {
          // handle error
          console.log(error);
          v_aria.innerHTML = "Error";
          v_aria.classList.add("text-danger");
          setCookie(project_name[i], "None", 365);
        });
    }

Cookie读写函数:

function setCookie(cname, cvalue, exdays) {
  const d = new Date();
  d.setTime(d.getTime() + exdays * 24 * 60 * 60 * 1000);
  let expires = "expires=" + d.toUTCString();
  document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
}

function getCookie(cname) {
  let name = cname + "=";
  let decodedCookie = decodeURIComponent(document.cookie);
  let ca = decodedCookie.split(";";
  for (let i = 0; i < ca.length; i++) {
    let c = ca[i];
    while (c.charAt(0) == " ") {
      c = c.substring(1);
    }
    if (c.indexOf(name) == 0) {
      return c.substring(name.length, c.length);
    }
  }
  return "";
}

原因分析

  1. 循环变量作用域问题:循环中使用了未声明的i,导致i成为全局变量。由于fetch是异步操作,当then或catch回调执行时,循环已完全结束,此时i的值等于project_ids.length(即5),project_name[5]不存在,结果为undefined,传入setCookie后就会生成名称为undefined的Cookie。
  2. getCookie函数语法错误:let ca = decodedCookie.split(";";缺少闭合括号,会导致该函数无法正常执行,虽不是生成undefined Cookie的直接原因,但会影响Cookie读取逻辑。

解决方案

1. 修复循环变量作用域

将循环中的i用let声明,确保每次循环创建独立作用域,让异步回调获取当前循环的正确索引:

for (let i = 0; i < project_ids.length; i++) {
  // ... 原循环内容
}

或在循环内部提前保存当前项目名称,避免依赖循环变量:

for (i = 0; i < project_ids.length; i++) {
  const currentProjectName = project_name[i];
  // 后续回调中用currentProjectName代替project_name[i]
  let cookie = getCookie(currentProjectName);
  if (cookie != json[0]["name"]) {
    v_aria.classList.add("bg-warning");
    setCookie(currentProjectName, json[0]["name"], 365);
  }
  // catch中同理
  setCookie(currentProjectName, "None", 365);
}

2. 修复getCookie函数的语法错误

将let ca = decodedCookie.split(";";修改为:

let ca = decodedCookie.split(";");

修改后的完整代码示例

主逻辑代码

const project_ids = [62, 37, 43, 67, 29];
const project_name = ["a", "b", "c", "d", "e"];

// 使用let声明循环变量i
for (let i = 0; i < project_ids.length; i++) {
      let v_aria = document.getElementById("v-" + project_name[i]);
      let aria_collapse = document.getElementById(
        project_name[i] + "-collapse"
      );
      let aria_link = document.getElementById(project_name[i] + "-link");
      let aria_data = document.getElementById(project_name[i] + "-data");
      fetch(
        "https://<my_domain>/api/v4/projects/" +
          project_ids[i] +
          "/releases",
        {
          method: "GET",
          headers: {
            "PRIVATE-TOKEN": GITTOKEN,
          },
        }
      )
        .then((response) => response.json())
        .then((json) => {
          v_aria.innerHTML = json[0]["name"];
          let link = json[0]["_links"].self;
          aria_link.innerHTML = '<a href="'.concat(
            link,
            '" target="_blank">Project</a>'
          );
          aria_data.innerHTML = json[0]["released_at"];
          let cookie = getCookie(project_name[i]);
          if (cookie != json[0]["name"]) {
            v_aria.classList.add("bg-warning");
            setCookie(project_name[i], json[0]["name"], 365);
          }
        })
        .catch(function (error) {
          console.log(error);
          v_aria.innerHTML = "Error";
          v_aria.classList.add("text-danger");
          setCookie(project_name[i], "None", 365);
        });
    }

Cookie读写函数

function setCookie(cname, cvalue, exdays) {
  const d = new Date();
  d.setTime(d.getTime() + exdays * 24 * 60 * 60 * 1000);
  let expires = "expires=" + d.toUTCString();
  document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
}

function getCookie(cname) {
  let name = cname + "=";
  let decodedCookie = decodeURIComponent(document.cookie);
  // 修复括号问题
  let ca = decodedCookie.split(";");
  for (let i = 0; i < ca.length; i++) {
    let c = ca[i];
    while (c.charAt(0) == " ") {
      c = c.substring(1);
    }
    if (c.indexOf(name) == 0) {
      return c.substring(name.length, c.length);
    }
  }
  return "";
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 08:44:56