Fetch请求首次点击无响应 二次点击才生效 读取name属性报错
Fetch请求对接宝可梦API异常修复
复现的异常表现
- 点击搜索按钮首次触发时,接口返回值无法正常展示,需要第二次点击功能才正常
- 第一次输入宝可梦编号点击搜索无响应,修改编号再次点击时,页面展示的是第一次输入编号对应的宝可梦数据
- fetch请求回调中打印日志可以正常拿到接口返回结果,但执行展示逻辑时控制台抛出错误:
Uncaught TypeError: Cannot read properties of undefined (reading 'name')
问题根因
所有异常都来自核心代码逻辑错误:
- Promise链式调用写法错误:
.then(displayPokemon())这行代码会在fetch请求发送后立即执行displayPokemon函数,而不是等接口返回、实例化完成后再执行。此时用来存宝可梦数据的变量还没被赋值,读取name属性自然会抛undefined错误;等你第二次点击时,第一次请求的异步结果刚好返回完成、给变量赋了值,就会出现展示数据滞后一次、首次点击无效的现象。 - 属性名不匹配:实例化Pokemon对象时传入的是接口返回的
sprites字段,但展示逻辑里写的是pokemon.image.front_default,修完时序问题后这里也会触发新的类型错误。 - 额外隐患:代码依赖全局变量存储宝可梦数据,异步时序错乱时很容易出现读写冲突。
修复后可直接运行的代码
// 修正原函数名多写字母t的拼写错误 const fetchPokemon = function (inputNum) { fetch(`${pokemonApi}${inputNum}`) .then(response => response.json()) .then(response => { // 实例化后直接返回给Promise链,不依赖全局变量暂存 return new Pokemon( response.name, response.sprites, response.moves, response.types, response.abilities ) }) // 传入函数引用而非执行结果,等实例化完成后再调用展示逻辑,通过参数传递数据 .then(pokemonData => displayPokemon(pokemonData)) // 新增请求错误捕获,方便排查接口异常 .catch(err => console.error('宝可梦数据请求失败:', err)) } // 展示函数通过参数接收数据,移除全局变量依赖 const displayPokemon = function (pokemon) { pokemonName.innerText = pokemon.name console.log(pokemon.name) // 修正属性名:匹配实例化时传入的sprites字段 pokemonImg.src = pokemon.sprites.front_default displayMoves(pokemon.moves) displayType(pokemon.types) displayAbilities(pokemon.abilities) }
关键修改说明
- 把
.then(displayPokemon())改为.then(pokemonData => displayPokemon(pokemonData)),确保展示逻辑在接口返回、数据实例化完成后才执行,彻底解决时序错乱导致的首次点击无效、数据滞后问题 - 移除全局变量存储数据的逻辑,通过Promise链、函数参数传递宝可梦实例,避免异步读写冲突
- 修正属性名错误,将展示逻辑里的
pokemon.image改为pokemon.sprites,和接口返回字段、实例化传参保持一致 - 新增catch分支捕获请求阶段的错误,接口报错时可以直接在控制台看到明确的错误提示
内容的提问来源于stack exchange,提问作者DoronDavid
相关产品推荐
相关产品推荐

