GraphQL

11 2月

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"}}

发表评论

电子邮件地址不会被公开。 必填项已用*标注