从数组获取索引返回undefined?JS记忆游戏开发遇问题
问题分析与解决方案
核心问题1:异步操作的时序错误
fetch是异步操作,你当前代码里的shuffle(images_list)和后续给卡片设置src的循环,都是在fetch请求还未完成、images_list还没被填充时就执行了。
你看到console.log(images_list)显示有36个元素,是因为浏览器控制台会动态更新数组的显示——打印时数组还是空的,但当你展开控制台的数组条目时,异步请求已经完成,数组被填充了。但实际代码执行到img.src = images_list[i]这一步时,images_list里还没有元素,所以访问任何索引都会返回undefined。
核心问题2:fetch调用次数不足
你当前只调用了一次fetch,只能获取1张图片,即便存两次也只有2个元素,根本凑不齐36张(18张各存两次)的需求。
修正后的代码实现
我们用async/await处理异步流程(比嵌套then更直观),同时用Promise.all批量发起18次请求,确保所有图片URL都获取完成后再处理数组和卡片:
// 标准Fisher-Yates洗牌实现(如果你的shuffle函数有问题可以用这个) function shuffle(array) { let currentIndex = array.length, randomIndex; while (currentIndex !== 0) { randomIndex = Math.floor(Math.random() * currentIndex); currentIndex--; [array[currentIndex], array[randomIndex]] = [array[randomIndex], array[currentIndex]]; } return array; } // 异步初始化游戏 async function initMemoryGame() { const imagesList = []; // 创建18个fetch请求的Promise const imageRequests = Array.from({ length: 18 }, () => fetch('https://dog.ceo/api/breeds/image/random').then(res => res.json()) ); // 等待所有请求完成,拿到所有图片数据 const imageDataList = await Promise.all(imageRequests); // 每张图片存入数组两次 imageDataList.forEach(data => { imagesList.push(data.message); imagesList.push(data.message); }); // 洗牌数组 shuffle(imagesList); // 为卡片设置图片src const backViewElements = document.getElementsByClassName("back-view"); for (let i = 0; i < backViewElements.length; i++) { const imgElement = backViewElements[i].querySelector("img"); imgElement.src = imagesList[i]; } } // 启动游戏初始化 initMemoryGame();
关键说明
- 异步流程控制:
await Promise.all(imageRequests)会等待所有18次fetch请求都完成后,才会继续执行后续代码,确保imagesList被正确填充。 - 批量请求:用
Array.from创建18个fetch请求的Promise,保证能获取18张不同的图片(API返回随机图,重复概率极低)。 - 避免控制台误导:现在所有操作都在异步请求完成后执行,
imagesList在设置卡片时已经有36个有效元素,不会再出现undefined的情况。
内容的提问来源于stack exchange,提问作者PiiMY
相关产品推荐
相关产品推荐

