能打印Pokemon数据但无法批量写入数据库,请求技术排查
问题:Pokemon数据种子脚本无法写入数据库,多次运行后完全失效
我可以通过console.log打印我的Pokemon数据,但无法将其导入(seed)到数据库中。最初运行种子文件时还能成功写入部分数据,但多次运行后就完全失效了。相关代码如下:
const Pokemon = require('../../models/Pokemon'); const faker = require('faker-br'); const axios = require('axios'); const seedPokemon = async function () { let PokemonArray = []; let i; for (i = 1; i < 50; i++) { axios.get(`https://pokeapi.co/api/v2/pokemon/${i}`).then(res => { PokemonArray.push({ name: res.data.name, height: res.data.height, pokédex_index: res.data.id, pokémon_type: res.data.types[0].type.name, sex: faker.random.arrayElement(['male', 'female', 'non-binary']), photo: res.data.sprites.front_default }) }) } try { await Pokemon.sync({ force: true }); await Pokemon.bulkCreate(PokemonArray); } catch (err) { console.log(err); } }; module.exports = seedPokemon;
请问我哪里操作出错了?恳请协助解决。
问题原因与修复方案
核心错误:异步请求未等待完成
你的代码存在异步时序问题:
- 循环中调用
axios.get是异步请求,这些请求会在后台执行,但代码不会等待它们完成,就直接执行了后续的Pokemon.sync和bulkCreate。 - 第一次运行偶尔写入部分数据,是因为个别请求刚好在
bulkCreate执行前完成;多次运行后,网络或事件循环的差异导致所有请求都没来得及填充数组,PokemonArray为空,自然无法写入数据库。
修复后的代码
修改思路:收集所有API请求的Promise,用Promise.all等待所有请求完成后,再执行数据库操作,同时用async/await简化异步逻辑:
const Pokemon = require('../../models/Pokemon'); const faker = require('faker-br'); const axios = require('axios'); const seedPokemon = async function () { try { // 收集所有API请求的Promise const pokemonPromises = []; for (let i = 1; i < 50; i++) { pokemonPromises.push( axios.get(`https://pokeapi.co/api/v2/pokemon/${i}`).then(res => { return { name: res.data.name, height: res.data.height, pokédex_index: res.data.id, pokémon_type: res.data.types[0].type.name, sex: faker.random.arrayElement(['male', 'female', 'non-binary']), photo: res.data.sprites.front_default }; }) ); } // 等待所有请求完成,获取完整的Pokemon数据数组 const PokemonArray = await Promise.all(pokemonPromises); // 同步数据库并批量插入数据 await Pokemon.sync({ force: true }); await Pokemon.bulkCreate(PokemonArray); console.log('Pokemon数据种子导入成功!'); } catch (err) { console.error('种子导入失败:', err); } }; module.exports = seedPokemon;
额外优化建议
- 单个请求错误处理:给每个axios请求单独添加catch,避免一个请求失败导致整个批量操作终止:
pokemonPromises.push( axios.get(`https://pokeapi.co/api/v2/pokemon/${i}`) .then(res => { return { /* 数据结构 */ }; }) .catch(err => { console.error(`获取第${i}个Pokemon数据失败:`, err); return null; // 返回null,后续过滤掉无效数据 }) ); // 过滤掉请求失败的空数据 const PokemonArray = (await Promise.all(pokemonPromises)).filter(item => item !== null);
- 控制并发请求数:如果请求数量很大,一次性发起太多请求可能触发API限流,可以分批处理或用第三方库(如
p-limit)控制并发数。
内容的提问来源于stack exchange,提问作者fipdev
相关产品推荐
相关产品推荐

