You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:38:50