graphQL

114 阅读2分钟

现有的问题

1.颗粒度问题

  1. 场景的复杂,不同终端的需求不一样,需要的字段不一样,颗粒度也不一样
  2. 多个接口合并问题

2.不同版本问题

  1. 多个版本参数与返回值不一样

3.通信双向问题接口定义

  1. 接口定义规范问题

4.组件状态需要分别管理

  1. 父子关系需要的传递问题
  2. 各个组件需要分发接口

graphQL作用

1.定义

前后端数据查询方式的规范

  1. 自由组合,定义命名
  2. 自由调整参数,返回值
  3. 定义订阅与监听响应事件,解决双向监听
  4. 有效的合并一个接口

2.例子

1. query查询

# 直接调接口
query {
 hello
}
# 执行结果
{
 "data": {
    "Hello world!"
   ]
 }
 
# 修改返回名称
query {
 helloNew:hello
}
# 执行结果
{
 "data": {
    helloNew:"Hello world!" 
}

# 查询指定字段
query {
   books {
       title,
       author
     }
}

### 执行结果
{
 "data": {
   "books": [
     {
       "title": "abc",
       "author": "xxxx"
     }
   ]
 }

# 合并两个接口参数
query {
   books {
       title,
       author
     },
   helloNew:hello
}
### 执行结果
{
 "data": {
   "books": [
     {
       "title": "abc",
       "author": "xxxx"
     }
   ],
     helloNew:"Hello world!"
}

2.Mutation 动作:新增修改删除

# 创建方法
mutation {
 createBook (title:"111",author:"2222"){
     id
 }
}
# 参数可以省略一部分
mutation {
 createBook (title:"111"){
     id
 }
}

3.subscribe 基于webstock的订阅发布机制

# 执行后 进入listening。。。等待监听模式
 #调用mutation方法变化数据,会自动触发
subscription {
    subsBooks
}

基于apollo-server代码实现

const { ApolloServer, gql, PubSub, withFilter } = require('apollo-server');
const pubsub = new PubSub() //实例化一个订阅发布对象
const typeDefs = gql`
 type Query {
   hello: String,
   books: [Book],
   book(id : String) : Book
 }

 type Book {
   id:String
   title: String
   author: String
 }

 type Mutation {
   createBook(title: String, author: String): Book!,
   clearBook : Boolean
 }
 type Subscription {
   subsBooks : Boolean,
 }
`;

//books 对象后续可以调整为 数据库操作
// clearBook():Book
const books = (
   () => Array(5).fill().map((v, i) => ({
       id: '' + i,
       title: 'Title' + i,
       author: 'Author' + i
   }))
)()
const resolvers = {}
resolvers.Query = {
   hello: () => 'Hello world!',
   books: () => books,
   book: (parent, { id }) => {
       return books.find(v => v.id === id)
   }
}


resolvers.Mutation = {
   createBook: (parent, args) => {
       const book = { ...args, id: books.length + 1 + '' }
       books.push(book)
       // 发布订阅消息
       pubsub.publish('UPDATE_BOOK', {
           subsBooks: true
       })
       return book
   },
   clearBook: () => {
       books.length = 0
       pubsub.publish('UPDATE_BOOK', {
           subsBooks: true
       })
       return true
   }
}

resolvers.Subscription = {
   subsBooks: {
       // 过滤不需要订阅的消息
       subscribe: withFilter(
       //这里通过UPDATE_BOOK 主键过滤监听事件
           (parent, variables) => pubsub.asyncIterator('UPDATE_BOOK'),
           (payload, variables) => true
       )
   },
}
const server = new ApolloServer({ typeDefs, resolvers });

server.listen().then(({ url }) => {
   console.log(`服务启动: ${url}`);
});