JSON fetch中使用insertAdjacentHTML报错及数组为空问题求助
问题分析与解决
核心问题:异步操作的作用域与执行顺序
你遇到的两个问题本质都是异步代码的执行时机和变量作用域导致的:
gitLinks[i]报错:for循环里的i是全局/函数级作用域变量,当fetch的回调执行时,循环已经全部执行完毕,i的值等于gitLinks.length,此时gitLinks[i]自然是undefined。虽然console.log(date)能输出,是因为回调里的date已经成功获取,但DOM元素的引用已经失效。jsonDates数组为空:同样是异步顺序问题,你在fetch回调外打印数组时,所有fetch请求还没完成,数组还没被填充,所以看起来是空的。
具体解决方案
方案1:用forEach遍历链接(最直观)
把for循环改成forEach,它会为每个元素创建独立的作用域,避免回调执行时变量失效:
const gitLinks = Array.from(document.querySelectorAll('a[href*="github.com"]')); const jsonDates = []; gitLinks.forEach(link => { // 替换成你生成JSON文件链接的实际逻辑 const jsonUrl = `xxx/${link.href.split('/').pop()}.json`; fetch(jsonUrl) .then(res => res.json()) .then(data => { const dateStr = `<strong>${data.date}</strong>`; link.insertAdjacentHTML('beforebegin', dateStr); jsonDates.push(data.date); }) .catch(err => console.error('请求失败:', err)); });
方案2:用let声明循环变量(坚持用for循环时)
把循环里的var i改成let i,let会在每次循环迭代时创建新的变量绑定:
const gitLinks = Array.from(document.querySelectorAll('a[href*="github.com"]')); const jsonDates = []; for (let i = 0; i < gitLinks.length; i++) { const link = gitLinks[i]; const jsonUrl = `xxx/${link.href.split('/').pop()}.json`; fetch(jsonUrl) .then(res => res.json()) .then(data => { const dateStr = `<strong>${data.date}</strong>`; link.insertAdjacentHTML('beforebegin', dateStr); jsonDates.push(data.date); }) .catch(err => console.error('请求失败:', err)); }
方案3:用async/await处理异步(清晰的顺序控制)
如果需要等待所有请求完成再做统一操作,用Promise.all配合async/await:
async function processLinks() { const gitLinks = Array.from(document.querySelectorAll('a[href*="github.com"]')); const jsonDates = []; const promises = gitLinks.map(async link => { const jsonUrl = `xxx/${link.href.split('/').pop()}.json`; const res = await fetch(jsonUrl); const data = await res.json(); const dateStr = `<strong>${data.date}</strong>`; link.insertAdjacentHTML('beforebegin', dateStr); jsonDates.push(data.date); return data.date; }); // 等待所有请求完成后再执行后续逻辑 await Promise.all(promises); console.log('所有日期已获取:', jsonDates); } processLinks();
补充说明
- 把
insertAdjacentHTML移到fetch外能执行,是因为此时i还在循环的有效范围内,同步代码直接执行了,但这时候你还没拿到date值,实际是无效操作。 - 记得加上
catch处理请求失败的情况,避免报错中断后续代码。
内容的提问来源于stack exchange,提问作者massiveZebra
相关产品推荐
相关产品推荐

