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 ""; }
原因分析
- 循环变量作用域问题:循环中使用了未声明的
i,导致i成为全局变量。由于fetch是异步操作,当then或catch回调执行时,循环已完全结束,此时i的值等于project_ids.length(即5),project_name[5]不存在,结果为undefined,传入setCookie后就会生成名称为undefined的Cookie。 - 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
相关产品推荐
相关产品推荐

