使用 node-fetch 调用 PokeAPI GraphQL:从零构建一个查询宝可梦完整资料的 Node.js 示例

发布时间:2026/10/2 8:02:35
使用 node-fetch 调用 PokeAPI GraphQL:从零构建一个查询宝可梦完整资料的 Node.js 示例 后端【免费下载链接】pokeapiThe Pokémon API项目地址https://gitcode.com/GitHub_Trending/po/pokeapi点击查看免费下载本文以 PokeAPI 仓库中的 graphql/v1beta/examples/node 示例为主线讲解如何用 Node.js 的node-fetch库向 PokeAPI 的 GraphQL 端点发送 POST 查询并解析出宝可梦的种族值、特性、属性、升级技能、遭遇地点、火红版持有道具等十余类资料。读完本文你将掌握 PokeAPI GraphQL 的查询封装方式、pokemon_v2_*命名空间下的过滤与聚合语法以及如何在本地复现同样的调用。示例背景Node 目录中的 pokemon.js仓库在graphql/v1beta/examples/node/目录下提供了 Node.js 语言的 GraphQL 调用示例其中 README.md 对该示例的说明非常精简——它只做了一件事使用node-fetch获取关于 Staryu 的信息并给出了两条运行命令npm i node pokemon.js而真正承载核心逻辑的是同目录下的 pokemon.js它的头部注释明确列出了这份脚本会获取的资料范围亲密度happiness是否传说宝可梦legendary/ 幻之宝可梦mythical世代generation栖息地habitat身高height体重weight图鉴 ID特性abilities种族值stats属性types通过升级可学会的技能learnable moves by leveling up可以在多少个地点被找到in how many locations it can be found在火红版Fire Red中可持有的道具holdable items图鉴描述文本flavor text也就是说一次 GraphQL 查询即可把宝可梦的物种级 个体级信息全部取回这正是 PokeAPI GraphQL 端点相比传统 REST 接口的典型优势按需嵌套关联数据一个请求拿齐整棵关系树。快速上手安装依赖并运行示例依赖node-fetch其版本约束记录在 package.json 中{ name: examples, version: 1.0.0, dependencies: { node-fetch: ^2.6.1 } }也就是说在使用前需要先进入graphql/v1beta/examples/node目录执行npm i或npm install安装依赖然后运行脚本npm i node pokemon.js脚本的默认查询对象是starmie宝石海星但你也可以像这样把任意宝可梦名称作为命令行参数传入node pokemon.js pikachu node pokemon.js staryu这一点来自 pokemon.js 的main()实现async function main() { const pokemon process.argv.slice(2)[0]; const { errors, data } await fetchPokemon_details(pokemon) if (errors) { console.error(errors) } console.log(JSON.stringify(data, null, 2)) }process.argv.slice(2)[0]取命令行第一个参数作为宝可梦名称未传参时fetchPokemon_details的默认参数namestarmie会生效。输出则通过JSON.stringify(data, null, 2)以带缩进的格式化 JSON 打印到控制台便于直接阅读。如果查询返回了errors字段例如传入了不存在的名称脚本会先将其打印到 stderr。核心封装fetchGraphQL 是如何工作的pokemon.js 将 GraphQL 请求封装成了一个名为fetchGraphQL的异步函数这是理解整个示例的关键async function fetchGraphQL(query, variables, operationName) { const result await fetch( https://beta.pokeapi.co/graphql/v1beta, { method: POST, body: JSON.stringify({ query: query, variables: variables, operationName: operationName }) } ) return await result.json() }几个要点端点请求发往https://beta.pokeapi.co/graphql/v1beta即 PokeAPI 的 v1beta GraphQL 端点。仓库中 Go 语言的同款示例 graphql/v1beta/examples/go/pokemon.go 使用的也是同一个 URL。HTTP 方法GraphQL 查询统一使用POST查询语句放在请求体里而不是 URL 上。请求体三要素queryGraphQL 查询字符串、variables变量字典用于参数化查询、operationName操作名当请求体中包含多个操作时用于指定执行哪一个。返回处理result.json()直接解析 JSON 响应随后main()从响应对象中解构出{ errors, data }分别处理。如果是在本地通过 Docker Compose 部署这套 API参考 docker-compose.ymlGraphQL 服务则运行在http://localhost:8080该端口配置记录在 graphql/v1beta/config.yaml 的endpoint: http://localhost:8080一项中。将上面fetch的 URL 换成本地地址即可离线复现本示例的全部行为。解析查询一次拿回整棵宝可梦数据树fetchPokemon_details函数内部的query模板字符串是一份完整的 GraphQL 查询。它先通过pokemon_v2_pokemonspecies根字段按名称过滤出物种再沿着外键关系逐层嵌套取回数据。下面分段拆解。物种级信息与 where 过滤query pokemon_details($name: String) { species: pokemon_v2_pokemonspecies(where: {name: {_eq: $name}}) { name base_happiness is_legendary is_mythical generation: pokemon_v2_generation { name } habitat: pokemon_v2_pokemonhabitat { name } ...$name: String声明了查询变量实际传入值在fetchGraphQL(query, {name: name}, pokemon_details)中给出。where: {name: {_eq: $name}}使用 Hasura 风格的_eq操作符做等值过滤_eq、_neq、_gt、_in等操作符是这套 GraphQL API 过滤体系的基础语法。generation: pokemon_v2_generation和habitat: pokemon_v2_pokemonhabitat是物种表上的对象关系object relationships通过外键直接取回所属世代与栖息地。对象关系的定义可以在 public_pokemon_v2_pokemonspecies.yaml 中看到例如pokemon_v2_generation基于generation_id外键、pokemon_v2_pokemonhabitat基于pokemon_habitat_id外键。聚合查询拿取一只宝可梦实例pokemon: pokemon_v2_pokemons_aggregate(limit: 1) { nodes { height name id weight ...物种species是一对多的一个物种可能对应多只宝可梦实例如不同形态、地区形态。因此这里用pokemon_v2_pokemons_aggregate(limit: 1)聚合查询加limit: 1只取第一只实例从中读取height、weight、id等个体级数据。对应的数组关系array relationships同样定义在 public_pokemon_v2_pokemonspecies.yaml 中pokemon_v2_pokemons基于pokemon_species_id外键反向的对象关系则在 public_pokemon_v2_pokemon.yaml 中pokemon_v2_pokemonspecy。特性、种族值与属性abilities: pokemon_v2_pokemonabilities_aggregate { nodes { ability: pokemon_v2_ability { name } } } stats: pokemon_v2_pokemonstats { base_stat stat: pokemon_v2_stat { name } } types: pokemon_v2_pokemontypes { slot type: pokemon_v2_type { name } }特性通过pokemon_v2_pokemonabilities_aggregate聚合取出每个节点再经pokemon_v2_ability对象关系拿到特性名称。种族值直接遍历pokemon_v2_pokemonstats同时带出base_stat数值与pokemon_v2_stat下的属性名hp、attack、defense 等。属性遍历pokemon_v2_pokemontypesslot表示属性槽位1 为主属性、2 为副属性type对象关系给出属性名称。注意一个值得学习的命名技巧字段别名。ability:、stat:、type:都是给嵌套对象起的别名让返回 JSON 的字段名更语义化同理species:、generation:、habitat:、pokemon:也都是别名用于在结果中把不同层级的同名概念区分开。升级技能带过滤的聚合 去重levelUpMoves: pokemon_v2_pokemonmoves_aggregate(where: {pokemon_v2_movelearnmethod: {name: {_eq: level-up}}}, distinct_on: move_id) { nodes { move: pokemon_v2_move { name } level } }这里同时展示了三种进阶语法where里嵌套关联过滤pokemon_v2_movelearnmethod: {name: {_eq: level-up}}表示只取通过升级学会的技能过滤条件可以沿着关系链下钻。distinct_on: move_id按move_id去重避免同一技能在不同版本/条件下重复出现。返回的level字段记录了学会该技能的等级。遭遇地点计数与火红版持有道具foundInAsManyPlaces: pokemon_v2_encounters_aggregate { aggregate { count } } fireRedItems: pokemon_v2_pokemonitems(where: {pokemon_v2_version: {name: {_eq: firered}}}) { pokemon_v2_item { name } rarity }aggregate { count }是聚合查询的标量聚合语法返回foundInAsManyPlaces数值即该宝可梦出现在多少个遭遇地点。fireRedItems通过where过滤版本为firered返回该版本下的持有道具及其rarity携带稀有度。pokemon_v2_encounters、pokemon_v2_pokemonitems、pokemon_v2_pokemonmoves等数组关系都登记在 public_pokemon_v2_pokemon.yaml 的array_relationships中全部基于数据库外键自动生成。图鉴描述文本双重过滤flavorText: pokemon_v2_pokemonspeciesflavortexts(where: {pokemon_v2_language: {name: {_eq: en}}, pokemon_v2_version: {name: {_eq: firered}}}) { flavor_text } } }图鉴文本同时按语言en和版本firered双重过滤返回火红版英文图鉴描述。where内多个条件是 AND 关系这是 Hasura 过滤语法的默认行为。运行效果与错误处理成功运行时脚本会打印类似下面的格式化 JSON节选{ species: [ { name: starmie, base_happiness: 50, is_legendary: false, is_mythical: false, generation: { name: generation-i }, habitat: { name: waters-edge }, pokemon: [ ... ], flavorText: [ ... ] } ] }注意几个结构细节pokemon_v2_pokemonspecies返回的是数组所以species字段是一个数组同理pokemon_v2_pokemons_aggregate的nodes也是数组。若查询出错data为null而errors数组携带错误信息此时main()会打印errors否则data被完整输出。如果传入一个不存在的名称如node pokemon.js pikachuuuu由于where过滤结果为空species会是一个空数组而不是报错——这是 GraphQL 过滤语义的正常表现阅读结果时需要注意空数组 ≠ 查询失败。举一反三同目录下的其他查询范本Node 示例只展示了一个查询但同目录的.gql文件提供了更多可迁移到 Node 的语法模式值得一并阅读gen3_species.gql演示关联过滤 排序 多查询并发。用where: {pokemon_v2_generation: {name: {_eq: generation-iii}}}过滤三代宝可梦order_by: {id: asc}排序并同时执行第二个查询统计每个世代的物种数量pokemon_v2_pokemonspecies_aggregate { aggregate { count } }。pokemon_stats.gql演示排序 限制 标量聚合。例如按height desc且is_default: {_eq: true}取最高的 3 只或用avg { base_happiness }计算平均亲密度。item_translations.gql演示双向翻译查询——既可以从语言出发列出所有道具名也可以从道具出发反向带出各语言译名。更复杂的实战样例还有 alola_road_encounters.gql、weakestPokemonAbleToBeatFireRedAlone.gql、best_poison_grass_pokemon.gql 等。这些查询同样可以直接投递到https://beta.pokeapi.co/graphql/v1beta或本地http://localhost:8080把其中的查询字符串替换进fetchGraphQL的第一个参数即可在 Node 中复用。若想体验交互式查询仓库还提供在线的 GraphQL Console详见 graphql/v1beta/examples/README.md。跨语言对照Go 版的同构实现如果后续要把这套调用迁移到 Go 后端可以参考 graphql/v1beta/examples/go/pokemon.go。它用标准库net/http向同一端点发起 POSTresp, err : http.Post(url, , bytes.NewReader(body))其查询内容与pokemon.js几乎逐字段一致默认查询对象是staryu只是把query、variables、operationName组装进了自定义的Operation结构体。对照阅读两份实现可以快速理解同一份 GraphQL 查询如何在不同语言生态中落地。小结从这份 Node 示例可以提炼出调用 PokeAPI GraphQL 的完整套路用node-fetch向https://beta.pokeapi.co/graphql/v1beta发POST请求请求体包含query、variables、operationName。用pokemon_v2_*命名空间定位根数据表用where_eq等操作符做过滤用order_by、limit控制结果集。借助元数据中声明的外键关系自由嵌套对象关系与数组关系一次查询取回宝可梦全量资料。需要聚合统计数量、均值、去重时改用*_aggregate根字段配合aggregate/distinct_on语法。运行时用process.argv支持命令行传参用errors/data分流处理查询异常。相关文件路径速查示例本体 graphql/v1beta/examples/node/pokemon.js、依赖声明 graphql/v1beta/examples/node/package.json、本地端点配置 graphql/v1beta/config.yaml、关系元数据 public_pokemon_v2_pokemon.yaml 与 public_pokemon_v2_pokemonspecies.yaml。赞分享后端【免费下载链接】pokeapiThe Pokémon API项目地址https://gitcode.com/GitHub_Trending/po/pokeapi点击查看免费下载相关推荐B站弹幕屏蔽词分享与部署指南B站弹幕屏蔽词分享与部署指南 Bilibili Blacklist 是一个用于分享和管理 B 站弹幕屏蔽词的 Web 应用。它把不同用户整理好的屏蔽词打包成屏后端Flower 中的 FedPer 基线复现指南Federated Learning with Personalization Layers 实现详解Flower 中的 FedPer 基线复现指南Federated Learning with Personalization Layers 实现详解 导读 后端如何快速使用PokeAPI完整的宝可梦数据API指南如何快速使用PokeAPI完整的宝可梦数据API指南 PokeAPI是一个功能强大的宝可梦数据API为开发者和爱好者提供全面的RESTful和GraphQL后端上一篇NetworkX 1.4 版本功能详解核心算法、文件格式与 API 变更指南下一篇CMakeRC安全最佳实践保护嵌入式资源免受未授权访问的终极指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询