首页 > 解决方案 > Graphql Api Chuck Norris

问题描述

我需要帮助构建一个包装 ChuckNorris.io API 的 GraphQL Api

API 应该具有解析所有类别的查询类型(https://api.chuckmorris.io/jokes/categories

Api 应该具有 Query 类型,可以解决作为参数给出的随机笑话 ( https://api.chucknorris.io/jokes/random?category= {category})

const express=require('express');
const {ApolloServer,gql}=require('apollo-server-express');
const fetch=require('node-fetch');

const typeDefs=gql`
type Joke{
    icon_url:String,
    id:String,
    url:String
    value: String
}

type Category{
    animal:String
    career:String
    celebrity:String
    dev:String
    explicit:String
    fashion:String
    food:String
    history:String
    money:String
    movie:String
    music:String
    political:Strig
    religion:String
    science:String
    sport:String
    travel:String
}

type Query{
    getCategory(category:String!):Joke
    category:Category
}

`

const resolvers={
  Query:{
 getCategory: async(_,{category})=>{
   const response=await fetch(`https://api.chucknorris.io/jokes/random?category=${category}`)
   return response.json();
  },
 category: async(_,{})=>{
   const response=await fetch('https://api.chucknorris.io/jokes/categories') 
   return response.json();
  }
  }
}


const server= new ApolloServer({typeDefs,resolvers});

const app=express();
server.applyMiddleware({app});

app.listen({port:4000},()=>
console.log('Now browse to http://localhost:4000' + server.graphqlPath)
)

标签: apollo-serverexpress-graphql

解决方案


您对类型类别的查询应该返回一个字符串列表(数组),所以

export const typeDefs = gql`
    type Joke {
        value: String!
        id:ID!
        icon_url:String!
    }
    type Query {
        getAllCategories:[String!]!
        randomJoke(category: String!):Joke
    }
`;

对于您的解析器,您不需要获取。apollo 提供数据源来连接到外部 REST API,就像您拥有的那样。所以安装 npm 包“apollo-datasource-rest”并将其添加到您的 apollo 服务器实例中,如下所示

const server = new ApolloServer({
    typeDefs,
    resolvers,
    dataSources: ()=>({
        jokeinstance : new Jokenorris
    })
})

然后为 Jokenorris 创建数据源类并正确导入或像您一样在一个 src 文件中执行所有操作。

import pkg from "apollo-datasource-rest";
const { RESTDataSource } = pkg;

export class Jokenorris extends RESTDataSource {
  constructor() {
    super();
    this.baseURL = "https://api.chucknorris.io/jokes";
  }
  

  async getAllCategories() {
    const res = await this.get("categories");
    return res;
  }

  async getRandomJoke({ category }) {
    const response = await this.get("random", { category: category });
    return response;
  }
}

那么您的解析器可能看起来像这样,如果您将所有内容分块在一个文件中,您可以忽略导出和导入

 export  const resolvers = {
      Query: {
        allJokeCategories: (_, __, { dataSources }) =>
          dataSources.jokeinstance.getAllCategories(),
          randomJoke: (_, {category}, {dataSources})=>
          dataSources.jokeinstance.getRandomJoke({category:category})
      },
    };

推荐阅读