Restful API根据http请求的路径和method去获取,请求方与服务方都很很容易理解。缺点是数据format和聚合依赖服务端或前端二次加工,例如前端只需要某接口中几个字段,服务端会将接口中所有字段都查询出来后返给前端,造成资源浪费。
GraphQL官网简介是:一种用于API的查询语言,即前端要什么就返回什么。
- GraphQL以API为单位,一个API即可获取客户端所有的数据,客户端将多次查询合并成一次查询,减少客户端的请求开销。Restful中是以资源为单位的
- GraphQL通过查看Schema即可知道服务端提供数据的所有能力,对开发友好
- Restful可以用不同http状态码代表不同异常,GraphQL总是返回200,对异常处理不太友好
- GraphQL生态不如Restful成熟,如缓存,防攻击(API需要暴露出去)等方面有待提高,核心业务慎用
const { buildSchema, graphql } = require('graphql') // 定义一个数据格式 schema,类似 protocol-buffers const schema = buildSchema(` type Query { hello: String } `) // 服务端的取值函数 const root = { hello: () => 'Hello world!' } // 运行Graphql,第一个参数是数据格式,第二个参数是要取哪个数据,第三个参数是从哪里取这个数据 graphql(schema, '{ hello }', root).then((responese) => { console.log(responese) })
都是自解释代码很容易看懂,只需要封装成函数,前端传入schema和需要取的数据,服务端用GraphQL将数据response返回给前端即可,可以用koa-graphql:
// schema.js const { buildSchema } = require('graphql') const schema = buildSchema(` type Person { // 定义数据结构 id: Int name: String } type Query { // 定义查询语句 person: [Person] } type Mutation { // 定义修改语句 location(id: Int, location: String): String } `) const mockData = [{ id: 1, name: "zhangsan", location: "shanghai" },{ id: 2, name: "lisi", location: "beijing" }] schema.getQueryType().getFields().person.resolve = () => { return mockData } schema.getMutationType().getFields().location.resolve = (args0, { id, location }) => { const idx = mockData.findIndex(item => { return item.id === id }) mockData[idx].location = location return mockData[idx].location } module.exports = schema
// index.js const koa = require('koa') const mount = require('koa-mount') const graphqlHTTP = require('koa-graphql') const app = new koa app.use( mount('/api', graphqlHTTP({ schema: require('./schema') }) ) app.listen(3000)
// 查询用get请求的query:http://localhost:3000/api/?query={person{id,name,location}} // 结果:{"data":{"person":[{"id":1,"name":"zhangsan","location":"shanghai"},{"id":2,"name":"lisi","location":"beijing"}]}} // 修改用post请求的body:http://localhost:3000/api/ // body:mutation {location(id: 2, location: "chengdu")} // 结果:{"data": {"location": "chengdu"}}