GraphQL入门

95 阅读3分钟

graphQL与传统的Reatful API相比的优势:

  1. graphQL只返回我们需要的数据,Reatful API返回冗余数据

  2. Reatful API在同一个url节点下的不同资源要发送不同的请求

    /users/:id
    /users/posts
    

对象类型和字段

在Graph中大多数类型是对象类型:

{
  hero {
    name
    appearsIn
  }
}
  1. 外层的大括号是root Object
  2. 选取了对象中的hero字段
  3. 选取hero字段返回的对象中的name和appearsIn字段

在服务器端:


type Character{
  name:String!
  appearsIn:[Episode!]!
}
  • Character 对象类型,指的是有字段的类型
  • name appearsIn 在Character 中的类型,在Character 类型的查询中,name和appearsIn是唯一会返回的字段
  • String 内置的标量类型,会被解析成单一的标量对象
  • String! 服务端承诺每当查询这个字段就会返回值
  • [Episode!]! 指的是一个由Episode对象组成的数组。每当查询appearsIn字段时,就会返回一个由Episode对象组成的数组

但是在Schema中,有2个特殊类型:Query和Mutation类型,特殊在于它们定义每个查询的入口节点。

每个GraphQL服务器都有query类型,不一定有mutation类型

Query获取数据

参数可以决定返回多少数据,只要最后2条数据

allPersons(last:2){
  name,
  age
}

客户端发送如下请求:


query{
  hero{
    name
  }
  droi(id:"2000"){
    name
  }
}

意味着服务器端有Query类型,其中有hero和droi字段


type Query {
  hero(episode:Episode):Character
  droi(id:ID!):Droi
}

Mutation同理

Mutations

创建,修改,删除数据就用mutation


mutation {
  createPerson(name:"Bob",age:36){//创建了一个人,并传入参数
    id//让服务器返回的东西  id是服务器自动生成的
    //可以在此获取修改后的数据
  }
}

Subscriptions

用Subscriptions实现客户端和服务器实时连接

当客户端订阅一个事件:发送subscription给服务端,客户端就和服务器维持了一个持久连接,不管该事件是否发生,当数据变动时,服务端都会推送响应数据给客户端。而不需要客户端发送请求。

每当mutation修改、更新、创建数据,服务器就会把新的数据推送给客户端


type Query {
  allPersons:[Person!]!
}
type Mutation {
  createPerson(name: String!, age: Int!): Person!
}
type Subscription {
  newPerson: Person!
}

Schema(模式)

GraphQL有自己的类型语言,Schema就是用来定义类型的模式,指定客户端如何请求数据,代表客户端和服务端之间的契约


type User{
  id:ID!
  name:String
}

定义了User类型,但是它不能给客户端提供任何功能,要给客户端提供功能,需要给类型添加根类型:Query、Mutation、Subscription

Schema根类型决定了哪些query和mutation能够被服务器接收,是服务器能力的抽象描述


//客户端才能够发送以下请求
query{
  user(id:"abc"){
    id
    name
  }
}
//只有在Schema中定义了有Query根节点的user字段
type Query{
  user(id:ID!):User
}

执行Query的原理

query请求只是一组字段,当服务器接收到query请求的时候,就会根据这些字段调用响应的解析器函数

const schema = new GraphQLSchema({
  query: new GraphQLObjectType({
    name: 'Query',
    fields: {
      user: {
        type: UserType,
        args: {
          id: { type: GraphQLID },
        },
        resolve: (root, args, context, info) => {
          const { id } = args // the `id` argument for this field is declared above
          return fetchUserById(id) // hit the database
        },
      },
    },
  }),
})
​
const UserType = new GraphQLObjectType({
  name: 'User',
  fields: {
    id: {
      type: GraphQLID,
      resolve: (root, args, context, info) => {
        return root.id
      },
    },
    name: {
      type: GraphQLString,
        // (root, args, context, info) 分别代表 
        //root  父节点,是上一次调用resolver函数的结果;
        //args 请求参数
        //context 解析器通信的方法
        //info 查询或变更的AST表示
      resolve: (root, args, context, info) => {
        return root.name
      },
    },
  },
})

嵌套多层的请求,可以用dataLoader来做性能优化