最近在折腾使用Github api作个微信小程序练练手,本篇文章就是在这个过程当中记录。html
直接先看下GraphQL的语法风格,感觉一下:前端
query {
repository(owner:"octocat", name:"Hello-World") {
id
}
}复制代码
这是最最最简单的一个运用示例,效果上等价于http://graphqlapi.xxx.com/query/repository?owner=octocat&name=Hello-World ,返回的内容格式是这样:node
再看下稍微复杂点的查询方式:git
query {
repository(owner:"octocat", name:"Hello-World") {
issues(last:20, states:CLOSED) {
edges {
node {
title
url
labels(first:5) {
edges {
node {
name
}
}
}
}
}
}
}
}复制代码
这是一个多级对象嵌套的查询,这里就不继续展开了。关于egde和node在下文会有少量讲解。对GraphQL有兴趣进行更深刻了解的能够自行研究学习,我本身也是刚入门,不坑你们了:),官网是graphql.org/(这个可能打不开,能够打开国内的地址graphql.cn),Facebook发布的规范在 facebook.github.io/graphql/Oct…。github
GraphQL 既是一种用于 API 的查询语言也是一个知足你数据查询的运行时。GraphQL 对你的 API 中的数据提供了一套易于理解的完整描述,使得客户端可以准确地得到它须要的数据,并且没有任何冗余,也让 API 更容易地随着时间推移而演进,还能用于构建强大的开发者工具。小程序
因为我须要作一个定时任务将github上的数据定时拉到本地,因此天然的选择了后端处理的方式。找了一下.net下的GraphQL客户端,用了这个graphql-client。代码以下:c#
var heroRequest = new GraphQLRequest
{
Query = graphql //这里填写query的内容。
};
var graphQLClient = new GraphQLClient("https://api.github.com/graphql");
graphQLClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("Safari", "537.36"));
//上面这行很关键,UserAgent必定要写上,要否则会出现403错误,花了很久才找到这个问题。
graphQLClient.DefaultRequestHeaders.Add("Authorization", "bearer token"); //这里的token是个占位,实际须要在Github上生成。
var graphQLResponse = graphQLClient.PostAsync(heroRequest).Result;复制代码
关于token的生成以及其它的一些环境准备工做,在github上有详细的描述,参见:developer.github.com/v4/guides/f…。后端
重要的事情说3遍:UserAgent必定要写上!! UserAgent必定要写上!! UserAgent必定要写上!!微信小程序
Github提供的API和相关文档在developer.github.com/v4/ 右侧的目录树上,此次笔者须要拉取github的大量repository库,因此用到的search接口(可是很奇怪,这个接口在文档中并无列出来,也不知道为何)。建议你们能够先在Github提供的explorer中先测试和验证,OK了在把代码写到实际的项目中。api
接着,笔者在实现本身须要的功能时又学习了2个概念,才能正常开展下面的工做。第一个是edge与node的概念,edge能够理解为一个分页对象,其中除了包含实际的数据外还有一个cursor(返回的每条数据的惟一标识,若是要分页的话用获得这个数据,配合before与after关键字来使用)字段,实际数据就是用node表示的。
另外GraphQL是强类型的,因此当笔者用到的search返回的结果并非一个明确的数据对象时,先须要经过node下的__typename字段来得到实际的对象是什么。代码以下:
query {
search(query:"language:c#",type:REPOSITORY,first:1){
edges{
cursor,
node{
__typename
}
}
}
}复制代码
获得的结果是:
{
"data": {
"search": {
"edges": [
{
"cursor": "Y3Vyc29yOjE=",
"node": {
"__typename": "Repository"
}
}
]
}
}
}复制代码
获得的实际的数据对象是Repository以后,经过查阅Github Api的文档获得该对象有哪些字段,而且从中选择须要的字段便可。这个就是GraphQL的设计自然优点之一,按需获取。单在接下去运用的时候又须要引入一个新的概念fragment,这个能够理解为一个模板,经过这个模板来向服务端指明须要获取的数据字段。代码以下:
fragment repFragment on Repository {
name,
forkCount,
url,
createdAt,
updatedAt,
licenseInfo{ //对象嵌套
nickname //licenseInfo的nickname字段
},
stargazers{ //对象嵌套
totalCount //stargazers的totalCount字段
}
}
query {
search(query:"language:c#",type:REPOSITORY,first:100){
edges{
cursor,
node{
__typename
...repFragment
}
}
}
}复制代码
好了,这样就获得我须要的结果了。
下面附上笔者作的Demo:github.com/ZacharyFan/…,其中的token在配置文件中自行替换便可。
最后附带提一下,GraphQL的出现,主要的场景仍是在于赋能前端开发,赋予了前端开发者自由组织和定制请求数据的能力。这是一个将先后端分离后的界限偏向前端的框架,因此直接在前端经过GraphQL访问后端数据是我的比较推崇的方式。目前前端很是火热的GraphQL框架也很多,主流的就是下面2个: apollo(https://github.com/apollographql/apollo-client)、relay(https://github.com/facebook/relay)。
GraphQL虽好,可是要真正在中大型项目中运用GraphQL,还有有很大的困难的,服务端须要支持到GraphQL的规范格式进行数据输出,我认为须要付出的成本可不小。哪怕的架设一层中间层,也须要解决诸如分发、聚合和性能等问题。
做者:Zachary_Fan
出处:www.cnblogs.com/Zachary-Fan…
若是你想及时获得我的自写文章的消息推送,欢迎扫描下面的二维码~。