最近项目用到了graphql,学习了一些并在公司做了一个小分享,希望对你有帮助

一、介绍

Graphql是一种面向数据的API查询语言


Graphql给前端提供一种强力的查询工具,我们可以根据自己定义(需要)的格式去拿数据,它有自己的一套类型(schema)系统,schema 是 type、interface、enum 和 union 的集合,用来构建你的 API 数据模型; 类型系统在客户端和服务端之间提供了强类型的条约;我们想要什么,它就会准确给你返回什么,无冗余;

二、对比API

优缺点对比

  1. API接口数量众多维护成本高:接口的数量多、颗粒度较粗;graphql单个查询即可返回需要的信息,服务端只需要对客户端暴露一个地址即可
//如,要查A的表哥的公司的老总的父亲的车子是什么,可能需要多个api组合进行查询,而graphql一步到位;
query {
user (name : “A”) {
cousin{
boss{
father{
car
}
}
}
}
}
// 一般REST API需要多个接口查询,面对当前业务,新增接口也是开发成本
  1. 接口扩展成本高, 需求更换时,涉及到多接口合并,前端会增加请求数,还需要做数据处理等;

  2. 传统API接口:后端更新接口字段,文档未及时更新,可能影响到前端;graphql直接面向数据,通过 GraphiQL或者hasura 等可视化调试引擎展现服务端能提供的所有数据,开发过程不再依赖接口文档;

  3. 基于目前大多数企业架构,GraphQL应用需要前后端统一改造,适用方案较少,风险和成本较高;推动难度较大;比较适用全栈项目;GraphQL数据库查询性能存在瓶颈,服务端那边是需要平衡接口复杂度与数据库查询语言之间的复杂度;

三、主要概念

  1. 定义 API Schema

Schema定义了字段的类型、数据的结构,描述了接口数据请求的规则,当我们进行一些错误的查询的时候 GraphQL 引擎会负责告诉我们哪里有问题,和详细的错误信息;

自定义类型的定义主要是在服务端完成

# src/schema.graphql

# 接口定义
interface UserInterface {
id: ID!
name: String!
age: Int
gender: Gender
} interface BobbyInterface{
hobby: String!
} # 枚举定义 一般声明一组取值是常量的列表,字段属性需要大写
enum Gender {
MAN
WOMAN
} # 对象User的定义,type类似js的对象
type UserInfo implements UserInterface { // 继承
id: ID!
name: String!
age: Int!
gender: Gender
} type UserHobby implements BobbyInterface {
id: ID!
name: String!
age: Int!
gender: Gender
hobby: String!
} # 定义联合类型,进行字段的拓展 union User = UserInfo | UserHobby # 定义Query入口
type Query { // 基本查询
user(id: String!): [User]
// 标量类型:GraphQL 中内置有一些标量类型 String、Int、Float、Boolean、ID(ID类型代表着一个独一无二的标识、类似主键),用户也可以定义自己的标量类型
// !符号表示该字段不可空
// []: List类型、表示某个字段返回不止一个标量类型的数据
} # 实现query查询 query{
user(name: "范德彪") {
id
name
age
gender
}
} # Graphql Mutation, Subscription 等特殊的根类型,用于定义 API Schema Mutation定义,实现RUD
type Mutation {
createUser(id: ID!, name: String!, email: String!, age: Int,gender: Gender): User!
updateUser(id: ID!, name: String, email: String, age: Int, gender: Gender): User!
deleteUser(id: ID!): User
}

  1. 解析函数 Resolver: 负责到数据库中取得数据并返回
Query {
articles {
id
author {
name
}
comments {
id
desc
author
}
}
}
  • 第一层解析,使用articles的Resolver获取解析数据,

  • 第二层解析

(1) id在Author类型中为标量类型,解析结束

(2) author在Author类型中为对象类型User,尝试使用User的Resolver获取数据,当前field解析完毕

(3) 之后对第二层解析的返回值,进行第三层解析,当前author还包含一个Query, name,直到它是标量类型,解析结束

  1. Subscription

用于监听数据变动、并靠 Websocket 等协议推送变动的消息给订阅方。

subscription {
userChanged { // 监听用户数据变动
name
id
}
}

四、应用

  1. React + Graphql

Apollo

Apollo React

Apollo 是基于 GraphQL 的全栈解决方案集合;包括了 apollo-client 和 apollo-server 。

客户端:

  • 创建react+apollo
// 快速创建react demo
$ npx create-react-app apollo-react-demo
$ cd apollo-react-demo
$ npm install apollo-boost @apollo/react-hooks graphql
$ npm start

  1. CURD
// 查询数据
{
delivery_config(where: {id: {_eq: "lmXVOrQ8RMKezj89yP9aqw3xpo1JNL"}}) {
id
type
delivery_config_extras {
id
value
key
}
}
}
// 更新数据
mutation {
update_delivery_config(where: {id: {_eq: "lmXVOrQ8RMKezj89yP9aqw3xpo1JNL"}}, _set: {foreign_type: 2}) {
affected_rows
}
}
// 插入数据
mutation {
insert_delivery_config(objects: {brand_id: "100011", foreign_type: 1, delivery_config_extras: {data: {key: "testkey", value: "test", id: 123453323, created: "1574927283661", modified: "1574927283663"}}, id: "111233", created: "1574927283666", modified: "1574927283633", type: 2}) {
returning {
brand_id
}
}
}
// 删除数据
// 先删除关联数据
mutation {
delete_delivery_config_extra(where: {id: {_eq: 123453323}}) {
affected_rows
}
} mutation {
delete_delivery_config(where: {id: {_eq: "111233"}}) {
affected_rows
}
}

使用fetch请求graphql操作

五、总结

  • Graphql主要是用来解决 API 设计问题的,至于怎么优化查询并不是它的重点,我们正在进行的配送服务,它有一套传统接口,也提供graphql文档、搜索引擎等,这样可以更大程度上去释放系统的可扩展性,可满足更多前端开发的需求;目前企业很多上线运行的稳定的项目,如果考虑引入graphql,其实也会有很高的人力和学习、开发成本,推行可能会有阻碍;

  • 其实真正使用什么样的工具,还是要根据自己项目的特点去选择合适的技术,不是看什么新就用什么。GraphQL 也有缺点,如一次性查询过多数据,提升了被 服务器被DDOS 的风险等,但是如果你的需求可以正好避开这些缺点,

    或者用限流持久化查询等方案解决问题,就可以尝试使用。

参考链接:

koa2+graphql server demo

apollo+react demo

github V4 graphql

redux 和 graphql

apollo文档

apollo中文参考

hasura文档

GraphQL 为何没有火起来?

宋小菜GraphQLParty

最新文章

  1. js取float型小数点后两位数的方法
  2. UbuntuLinux安装Mysql
  3. redis.conf 配置详解 (转)
  4. 【BZOJ】1014: [JSOI2008]火星人prefix(splay+hash+二分+lcp)
  5. Android内存Activity泄露:Threads
  6. lib和dll的区别,生成(转)
  7. android性能小贴士 翻译
  8. ACM YTU 1012 u Calculate e
  9. javascript 弹框提示选择
  10. 使用autoCompleteTextView以及MultiAutoCompleteTextView实现自动匹配输入内容
  11. IOS9新特性之Contacts联系人
  12. spring-struts2-mybatis-maven 转账开发记录
  13. VS2017在线安装包下载
  14. jenkins使用开始踩坑(1)
  15. matlab飞机飞行
  16. Office Web addin 踩坑计:替换后台网站为MVC框架时遇到的问题
  17. Caused by: java.sql.SQLException: Field 'category_id' doesn't have a default value
  18. 自己用过的一些比较有用的css3新属性
  19. Python开发【Tornado】:搭建文件下载服务、音频文件播放
  20. Linux系统——Keepalived高可用集群

热门文章

  1. sql语句replace函数的使用
  2. Nmap常见扫描方式流量分析
  3. Disruptor 高性能并发框架二次封装
  4. scrapy(四): 爬取二级页面的内容
  5. linux09 /消息队列、saltstack工具
  6. 文件上传漏洞fuzz字典生成脚本小工具分享
  7. ASP.NET Core3.1使用Identity Server4建立Authorization Server-2
  8. Spring Bean前置后置处理器的使用
  9. 集训作业 洛谷P1135 奇怪的电梯
  10. python 模型的释义