摘要:系列文章核心概念浅尝本文常言道,实践是检验真理的唯一标准。遵循传统,第一个例子必须是。官方提供这个中间件来支持基于的查询,所以,这里选用作为服务器。首先是,这里对做了一点小修改,给几个字段添加了不能为空的设计。
系列文章:
GraphQL 核心概念
graphql-js 浅尝(本文)
常言道,实践是检验真理的唯一标准。
上一篇文章讲了 GraphQL 的核心概念,所提到的一些例子都是理论化的,并没有实际代码做支撑,就好像在画一个大饼,总是让人不那么信服。
它真的有那么神奇吗?那就同我一起看下去,用事实说话。
之前那篇文章一直有提到 GraphQL 是一个概念,每个语言可以有自己实现它的方式。因为,我是搞前端的,对 JavaScript 比较熟悉,所以,这里就用 graphql-js(GraphQL 的 JavaScript 实现)来举例。
Hello World遵循传统,第一个例子必须是 Hello World。
首先,安装就不用多说了。
npm install graphql --save
那这个例子该怎么设计哪?假设,查询一个 hello 字符串,就返回一个 world 字符串,很明显 type 的结构就该是这样
type HelloWorld { hello: String }
如何实现这个 HelloWorld 类型哪?graphql-js 已经定义好了基础类,我们直接调用就行。那么,这个 type 实现起来也就非常简单了
import { GraphQLString, GraphQLObjectType, } from "graphql"; const HelloWorldType = new GraphQLObjectType({ name: "HelloWorldType", fields: () => ({ hello: { type: GraphQLString, } }) });
简单分析一下上面的代码,可以看到 HelloWorldType 是一个 GraphQLObjectType 的实例,它包含一个 fields 是 hello,这个 hello 所对应的返回类型是字符串。
那如何返回 world 字符串?那就给它个 resolve 方法
const HelloWorldType = new GraphQLObjectType({ name: "HelloWorldType", fields: () => ({ hello: { type: GraphQLString, resolve() { return "world"; }, } }) });
这样类型就定义好了,还记不记得上篇文章提到的类型定义完成后该怎么办?
对,创建查询的 schema。
import { GraphQLString, GraphQLObjectType, GraphQLSchema, } from "graphql"; const HelloWorldType = new GraphQLObjectType({ name: "HelloWorldType", fields: { hello: { type: GraphQLString, resolve() { return "world"; }, } } }); const schema = new GraphQLSchema({ query: HelloWorldType });
schema 设置好了,是不是想查询看看哪?
东风当然是服务器啦。GraphQL 官方提供 express-graphql 这个中间件来支持基于 GraphQL 的查询,所以,这里选用 Express 作为服务器。
安装就不再重复了,只需将刚刚建立的 schema 添加到 express 的中间件中就可以了。
const app = express(); app .use("/graphql", graphqlHTTP({ schema, pretty: true })) .listen(3000, () => { console.log("GraphQL server running on http://localhost:3000/graphql"); });
当当当当~完成,去 Postman 里查询 http://localhost:3000/graphql?query={hello} 看看吧。
Blog System在上一篇文章里,我们设计了一个博客的查询 schema,这次我们就来动手实现它。(下面就开始讲例子啦,不愿听我唠叨的可以直接看代码)
前面 HelloWorld 的例子讲的比较详细,现在大家熟悉了语法,接下来的案例就会过得快一些。
首先是 PostType,这里对 Posttype 做了一点小修改,给几个字段添加了不能为空的设计。
/** * type Post { * id: ID!, * name: String!, * createDate: String!, * title: String!, * subtitle: String, * content: String, * tags: [Tag] * } */ const Post = new GraphQLObjectType({ name: "PostType", fields: () => ({ id: { type: new GraphQLNonNull(GraphQLID) }, name: { type: new GraphQLNonNull(GraphQLString) }, createDate: { type: new GraphQLNonNull(GraphQLString) }, title: { type: new GraphQLNonNull(GraphQLString) }, subtitle: { type: GraphQLString }, content: { type: GraphQLString }, tags: { type: new GraphQLList(TagType), resolve: post => post.tags.map(tagName => getTagByName(tagName)) } }) });
然后是另一个主要的 type: Tag type。
/** * type Tag { * id: ID!, * name: String!, * label: String!, * createDate: String!, * posts: [Post] * } */ const Tag = new GraphQLObjectType({ name: "TagType", fields: () => ({ id: { type: new GraphQLNonNull(GraphQLID) }, name: { type: new GraphQLNonNull(GraphQLString) }, label: { type: new GraphQLNonNull(GraphQLString) }, createDate: { type: new GraphQLNonNull(GraphQLString) }, posts: { type: new GraphQLList(PostType), resolve: tag => getPostsList().filter(post => ~post.tags.indexOf(tag.name)) } }) });
两个主要的类型已经定义好了,把它们俩整合起来就是博客类型了。
/** * type Blog { * post: Post, // 查询一篇文章 * posts: [Post], // 查询一组文章,用于博客首页 * tag: Tag, // 查询一个标签 * tags: [Tag], // 查询所有标签,用于博客标签页 * } */ const BlogType = new GraphQLObjectType({ name: "BlogType", fields: () => ({ post: { type: PostType, args: { name: { type: GraphQLString } }, resolve: (blog, { name }) => getPostByName(name), }, posts: { type: new GraphQLList(PostType), resolve: () => getPostsList(), }, tag: { type: TagType, args: { name: { type: GraphQLString } }, resolve: (blog, { name }) => getTagByName(name), }, tags: { type: new GraphQLList(TagType), resolve: () => getTagsList(), } }) });
这里有一个新东西,就是 arg 字段,用来获取查询参数,如果在没有设置过 arg 字段的属性上添加变量进行查询,graphql-js 的验证系统会报错。
最后,将之前的 helloworld 类型稍微修饰一下,独立出来,然后和 blog type 整合到一起成为根查询类。
const queryType = new GraphQLObjectType({ name: "RootQueryType", fields: () => ({ hello: WorldType, blog: { type: BlogType, resolve: () => ({}) }, }) }); const schema = new GraphQLSchema({ query: queryType });
OK。这样整个 Demo 就完成了(查看源码戳这里),快去 Postman 试试各种查询,体验 GraphQL 的神奇吧。(不知道怎么写查询语句的就看上一篇吧)
最后如果,你不喜欢 GET 方法或查询字符串过长,express-graphql 也支持 POST 方法,服务器会先查看请求的 URL 中是否包含查询字符串,如果不包含就会去 request body 中获取,只需在 request header 中将 Content-Type 设置为 application/graphql 就可以了。
全文一直在说查询,或许你会疑惑,那我修改怎么做哪?graphql 中的修改称之为 mutation。mutation 可以定义自己的接口解析类,它在 graphql 的 schema 中是一个可选项,其他的和查询并无两样,只是最后在 resolve 方法中的处理方式不同而已。
const schema = new GraphQLSchema({ query: queryType, mutation: mutationType });
最后的最后提一句,nodemon 很好用,谁用谁知道。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/91643.html
摘要:系列文章核心概念本文浅尝最近因为工作上新产品的需要,让我有机会了解和尝试。这篇文章主要分享的是的核心概念,主要分为和四部分。再次强调,本文主要讲的是的核心概念,中所定义的类,都是设计类,并不是具体实现代码。 A query language created by Facebook for describing data requirements on complex applicati...
Updated GraphQL Sync in ArangoDB 3.2 Just in time for the upcoming 3.2.0 release, we have updated the graphql-sync module for compatibility with graphql-js versions 0.7.2, 0.8.2, 0.9.6 and 0.10.1. The...
Updated GraphQL Sync in ArangoDB 3.2 Just in time for the upcoming 3.2.0 release, we have updated the graphql-sync module for compatibility with graphql-js versions 0.7.2, 0.8.2, 0.9.6 and 0.10.1. The...
Updated GraphQL Sync in ArangoDB 3.2 Just in time for the upcoming 3.2.0 release, we have updated the graphql-sync module for compatibility with graphql-js versions 0.7.2, 0.8.2, 0.9.6 and 0.10.1. The...
阅读 3714·2023-04-25 16:32
阅读 2090·2021-09-28 09:36
阅读 2010·2021-09-06 15:02
阅读 637·2021-09-02 15:21
阅读 894·2019-08-30 15:56
阅读 3485·2019-08-30 15:45
阅读 1669·2019-08-30 13:09
阅读 352·2019-08-29 16:05