JS异步函数三次调用后目标对象被覆盖,如何精准定位对应数据?
解决异步调用后图片点击获取对应组数据的问题
问题原因
你遇到的是异步调用中变量作用域被覆盖的问题:三次异步调用完成后,你用来存储结果的result变量最后会指向第三次调用的数组,所有图片的点击事件都引用了这个变量,所以不管点击哪组的图片,都会从最后一次的结果里取数据。
解决方法
下面给你两种简单易懂的实现方式,核心都是把每组的数据和对应的图片绑定起来,避免被后续调用覆盖:
方法一:全局数组存所有组结果 + 自定义数据属性标记
这种方式最直观,适合新手理解:
- 先定义一个全局数组,用来保存每一组的电影数据:
const allMovieGroups = [];
- 修改异步请求函数,把每组结果存入全局数组,同时给图片添加标记组和组内位置的自定义属性:
async function fetchMovies(endpoint) { // 发起请求并解析数据 const response = await fetch(`你的API前缀/${endpoint}`); const data = await response.json(); // 记录当前组的索引(全局数组的长度就是新组的索引) const groupIndex = allMovieGroups.length; // 把当前组的结果存入全局数组 allMovieGroups.push(data.results); // 遍历当前组的电影,创建图片元素 data.results.forEach((movie, itemIndex) => { const img = document.createElement('img'); img.src = `你的图片前缀/${movie.poster_path}`; // 添加自定义数据属性,标记组和组内位置 img.dataset.groupIndex = groupIndex; img.dataset.itemIndex = itemIndex; // 绑定点击事件 img.addEventListener('click', handleImageClick); // 把图片添加到对应组的DOM容器(比如给每个组容器加id:group-0、group-1...) document.getElementById(`group-${groupIndex}`).appendChild(img); }); } // 图片点击事件处理函数 function handleImageClick(e) { // 从图片属性里拿到组索引和项索引 const groupIndex = Number(e.target.dataset.groupIndex); const itemIndex = Number(e.target.dataset.itemIndex); // 从全局数组取出对应的数据 const targetMovie = allMovieGroups[groupIndex][itemIndex]; // 这里就可以使用目标电影对象了 console.log(targetMovie); } // 执行三次请求 fetchMovies('popular'); fetchMovies('top_rated'); fetchMovies('upcoming');
方法二:用闭包固定每组的结果
闭包可以让点击事件“记住”当前组的电影数据,不会被后续调用覆盖:
async function fetchMovies(endpoint) { const response = await fetch(`你的API前缀/${endpoint}`); const data = await response.json(); const currentGroupMovies = data.results; currentGroupMovies.forEach((movie, itemIndex) => { const img = document.createElement('img'); img.src = `你的图片前缀/${movie.poster_path}`; img.dataset.itemIndex = itemIndex; // 用立即执行函数创建闭包,把当前组的结果传进去 img.addEventListener('click', (function(groupMovies) { // 返回的函数会保留对groupMovies的引用 return function(e) { const itemIndex = Number(e.target.dataset.itemIndex); const targetMovie = groupMovies[itemIndex]; console.log(targetMovie); } })(currentGroupMovies)); // 添加到对应DOM容器 document.getElementById('你的组容器id').appendChild(img); }); } // 执行三次请求 fetchMovies('popular'); fetchMovies('top_rated'); fetchMovies('upcoming');
总结
两种方法的核心都是让每张图片的点击事件关联到自己所属组的原始数据,而不是共用一个会被覆盖的变量。第一种方法更直观,容易调试;第二种方法不用全局数组,适合不想用全局变量的场景。
内容的提问来源于stack exchange,提问作者Liti
相关产品推荐
相关产品推荐

