作为前端开发,想必经常做的事情就是:调接口、画页面、调接口、画页面...
调用的接口大概率是 restful 的,也就是类似这种:
/students 查询所有学生信息
/student/1 查询 id 为 1 的学生信息
上面说的是 get 请求。
如果对 /student/1 发送 POST、PUT、DELETE 请求,就分别代表了新增、修改、删除。
这就是 restful 风格的 web 接口。
这种接口返回什么信息是服务端那边决定的,客户端只是传一下参数。
而不同场景下需要的数据不同,这时候可能就得新开发一个接口。特别是在版本更新的时候,接口会有所变动。
这样就很容易导致一大堆类似的接口。
facebook 当时也遇到了这个问题,于是他们创造了一种新的接口实现方案:GraphQL。
用了 GraphQL 之后,返回什么数据不再是服务端说了算,而是客户端自己决定。
服务端只需要提供一个接口,客户端通过这个接口就可以取任意格式的数据,实现 CRUD。
比如想查询所有的学生,就可以这样:
想再查询他们的年龄,就可以这样:
想查询老师的名字和他教的学生,就可以这样:
而这些都是在一个 http 接口里完成的!
感受了 GraphQL 的好处了没?
一个 http 接口就能实现所有的 CRUD!
那这么强大的 GraphQL 是怎么实现的呢?
我们先写个 demo 快速入门一下:
facebook 提供了 graphql 的 npm 包,但那个封装的不够好,一般我们会用基于 graphql 包的 @apollo/server 和 @apollo/client 的包来实现 graphql。
首先引入这个包:
import { ApolloServer } from '@apollo/server';
然后写一段这样的代码:
import { ApolloServer } from '@apollo/server';
const typeDefs = `
type Student {
id: String,
name: String,
sex: Boolean
age: Int
}
type Teacher {
id: String,
name: String,
age: Int,
subject: [String],
students: [Student]
}
type Query {
students: [Student],
teachers: [Teacher],
}
schema {
query: Query
}
`;
比较容易看懂,定义了一个 Student 的对象类型,有 id、name、sex、age 这几个字段。
又定义了一个 Teacher 的对象类型,有 id、name、age、subject、students 这几个字段。students 字段是他教的学生的信息。
然后定义了查询的入口,可以查 students 和 teachers 的信息。
这样就是一个 schema。
对象类型和对象类型之间有关联关系,老师关联了学生、学生也可以关联老师,关联来关联去这不就是一个图么,也就是 graph。
GraphQL 全称是 graph query language,就是从这个对象的 graph 中查询数据的。
现在我们声明的只是对象类型的关系,还要知道这些类型的具体数据,取数据的这部分叫做 resolver。
const students = [
{
id: '1',
name: async () => {
await '取数据';
return '光光'
},
sex: true,
age: 12
},
{
id: '2',
name:'东东',
sex: true,
age: 13
},
{
id: '3',
name:'小红',
sex: false,
age: 11
},
];
const teachers = [
{
id: '1',
name: '神光',
sex: true,
subject: ['体育', '数学'],
age: 28,
students: students
}
]
const resolvers = {
Query: {
students: () => students,
teachers: () => teachers
}
};
resolver 是取对象类型对应的数据的,每个字段都可以写一个 async 函数,里面执行 sql、访问接口等都可以,最终返回取到的数据。
当然,直接写具体的数据也是可以的。
这里我就 student 里那个 name 用 async 函数的方式写了一下。
这样有了 schema 类型定义,有了取数据的 resovler,就可以跑起 graphql 服务了。
也就是这样:
import { startStandaloneServer } from '@apollo/server/standalone'
const server = new ApolloServer({
typeDefs,
resolvers,
});
const { url } = await startStandaloneServer(server, {
listen: { port: 4000 },
});
console.log(`