JavaScript增量搜索时出现shows不可迭代错误求助
解决你的TVMaze搜索增量加载错误
嘿,我来帮你搞定这个问题!首先你猜的没错,清空输入框时的错误确实是因为没有可遍历的对象,但根源是你的clearList函数里的一个小失误,还有几个其他潜在问题我也一起帮你梳理下:
主要错误原因:无参数调用makeImages()
当你清空输入框、页面没有图片的时候,clearList里执行了return makeImages();——这里你没有传任何参数,所以makeImages的shows参数变成了undefined,而for...of循环没法遍历undefined,自然就抛出了TypeError: shows is not iterable的错误。
完整修复方案
1. 修复clearList函数的逻辑
首先给生成的结果容器加一个专属class,比如"results-container",这样就能精准定位到我们要删除的div,不会误删页面里的其他div,同时去掉无参数调用makeImages的错误代码:
let clearList = () => { // 精准找到我们创建的结果容器 const oldDiv = document.querySelector(".results-container"); if (oldDiv) { oldDiv.remove(); } };
2. 修正makeImages里的作用域与报错问题
你在if(result.show.image)块里定义了yearNum,但外面的if(yearNum <= 2000)会在result.show.image不存在时找不到这个变量,导致ReferenceError。另外还要处理result.show.premiered为空的情况,避免字符串截取报错:
const makeImages = (shows) => { // 创建结果容器,加上专属class const div = document.createElement("div"); div.className = "results-container"; for (let result of shows) { if (result.show.image) { const img = document.createElement("IMG"); img.className += "resultImage"; img.src = result.show.image.medium; const title = document.createElement("h3"); title.className += "resultTitle"; title.innerText = result.show.name; const year = document.createElement("h4"); year.className += "score"; year.innerText = result.show.premiered || "未知年份"; // 先判断premiered是否存在,避免substring报错 let yearNum = null; if (result.show.premiered) { const sub = year.innerText.substring(0, 4); yearNum = parseInt(sub); } div.append(year); div.append(img); div.append(title); // 只有yearNum存在且小于等于2000时,才添加retro标签 if (yearNum !== null && yearNum <= 2000) { const retro = document.createElement("h5"); retro.className = "retro"; retro.innerText = "retro"; div.append(retro); } } } document.body.appendChild(div); };
3. 优化输入事件监听
input事件不需要e.preventDefault()(它本身没有默认行为),另外建议加一个防抖函数,避免用户快速输入时频繁调用API(比如输入"friends"会触发6次请求,防抖可以合并成1次):
const input = document.querySelector("#query"); // 防抖函数:延迟执行请求,避免频繁调用API const debounce = (func, delay) => { let timeoutId; return (...args) => { clearTimeout(timeoutId); timeoutId = setTimeout(() => func.apply(this, args), delay); }; }; // 包装搜索函数 const searchShows = async (searchTerm) => { clearList(); // 先清空旧结果,再请求新的 if (!searchTerm.trim()) return; // 如果输入为空,直接返回,不调用API const config = { params: { q: searchTerm } }; const res = await axios.get(`http://api.tvmaze.com/search/shows`, config); makeImages(res.data); }; // 绑定防抖后的事件 input.addEventListener("input", debounce((e) => { const searchTerm = e.target.value; searchShows(searchTerm); }, 300)); // 300ms延迟,可根据需求调整
额外说明
- 现在清空输入框时,
searchShows会因为searchTerm为空直接返回,不会调用API也不会执行makeImages,自然就不会触发错误。 - 给结果容器加专属class后,
clearList只会删除我们生成的结果div,不会影响页面其他元素。 - 防抖函数能有效减少API请求次数,提升性能和用户体验。
内容的提问来源于stack exchange,提问作者DMQuinn
相关产品推荐
相关产品推荐

