Node/Express调用PokeAPI仅返回单元素且报ERR_HTTP_HEADERS_SENT错误求助
问题原因
核心报错原因
Error [ERR_HTTP_HEADERS_SENT]报错和仅返回第一个元素的问题同源:你在routes/index.js的getPokemonData方法中,遍历宝可梦列表时每遍历到一个元素就调用一次res.json()。而Express的res.json()方法会直接完成本次请求的响应发送,同时关闭当前连接,所以第一次遍历就将第一个宝可梦的URL返回给了前端,后续遍历再调用res.json()时,因为响应已经发送完毕,无法重复设置响应头,就会抛出该错误。
附带代码问题
- 异步逻辑写法混乱,
await和.then混用,且未对异步请求做错误捕获后的响应处理 app.js的错误处理中间件中存在拼写错误:res.headesSent应为res.headersSent,会导致错误处理逻辑失效
修复方案
1. 修复路由逻辑(两种可选方案)
根据你的需求选择对应方案替换routes/index.js的代码即可:
方案一:仅返回所有宝可梦的URL列表
const express = require('express'); const router = express.Router(); const fetch = require('node-fetch'); router.get("/", async (req, res) => { try { // 拉取151只宝可梦的基础列表 const listResponse = await fetch(`https://pokeapi.co/api/v2/pokemon?limit=151`); const listData = await listResponse.json(); // 收集所有URL组成数组后一次性返回 const pokemonUrlList = listData.results.map(poke => poke.url); res.json(pokemonUrlList); } catch (error) { console.error('拉取数据失败:', error); res.status(500).json({ error: '宝可梦数据拉取失败' }); } }); module.exports = router;
方案二:返回所有宝可梦的完整详情数据
如果需要直接获取宝可梦的名称、图片等完整信息,使用该方案并发拉取所有详情后统一返回:
const express = require('express'); const router = express.Router(); const fetch = require('node-fetch'); router.get("/", async (req, res) => { try { // 拉取151只宝可梦的基础列表 const listResponse = await fetch(`https://pokeapi.co/api/v2/pokemon?limit=151`); const listData = await listResponse.json(); // 并发拉取每只宝可梦的详情数据 const detailPromiseList = listData.results.map(poke => fetch(poke.url).then(res => res.json())); const allPokemonDetail = await Promise.all(detailPromiseList); res.json(allPokemonDetail); } catch (error) { console.error('拉取数据失败:', error); res.status(500).json({ error: '宝可梦数据拉取失败' }); } }); module.exports = router;
2. 修复app.js拼写错误
找到app.js中的错误处理中间件,将res.headesSent修改为res.headersSent:
app.use((err, req, res, next) => { // 修正拼写错误 if(res.headersSent){ return next(err); } res.status(err.status || 500).json({ "errors": [ { "status": err.status, "title": err.message, "detail": err.message } ] }) })
3. 前端适配调整
后端返回的是宝可梦数据数组,前端拿到数据后遍历渲染即可:
await fetch('http://localhost:1337') .then(response => response.json()) .then(data => { console.log(data); // 遍历数组渲染每只宝可梦 data.forEach(pokemon => { const imgPokemon = pokemon.sprites.other['official-artwork']['front_default'] const namePokemon = pokemon.species.name; // 补充你的渲染逻辑即可 }) })
内容的提问来源于stack exchange,提问作者LJS100
相关产品推荐
相关产品推荐

