资讯专栏INFORMATION COLUMN

graphql-js 浅尝

gyl_coder / 2144人阅读

摘要:系列文章核心概念浅尝本文常言道,实践是检验真理的唯一标准。遵循传统,第一个例子必须是。官方提供这个中间件来支持基于的查询,所以,这里选用作为服务器。首先是,这里对做了一点小修改,给几个字段添加了不能为空的设计。

</>复制代码

  1. 系列文章:

  2. GraphQL 核心概念

  3. graphql-js 浅尝(本文)

常言道,实践是检验真理的唯一标准。

上一篇文章讲了 GraphQL 的核心概念,所提到的一些例子都是理论化的,并没有实际代码做支撑,就好像在画一个大饼,总是让人不那么信服。

它真的有那么神奇吗?那就同我一起看下去,用事实说话。

之前那篇文章一直有提到 GraphQL 是一个概念,每个语言可以有自己实现它的方式。因为,我是搞前端的,对 JavaScript 比较熟悉,所以,这里就用 graphql-js(GraphQL 的 JavaScript 实现)来举例。

Hello World

遵循传统,第一个例子必须是 Hello World。

首先,安装就不用多说了。

</>复制代码

  1. npm install graphql --save

那这个例子该怎么设计哪?假设,查询一个 hello 字符串,就返回一个 world 字符串,很明显 type 的结构就该是这样

</>复制代码

  1. type HelloWorld {
  2. hello: String
  3. }

如何实现这个 HelloWorld 类型哪?graphql-js 已经定义好了基础类,我们直接调用就行。那么,这个 type 实现起来也就非常简单了

</>复制代码

  1. import {
  2. GraphQLString,
  3. GraphQLObjectType,
  4. } from "graphql";
  5. const HelloWorldType = new GraphQLObjectType({
  6. name: "HelloWorldType",
  7. fields: () => ({
  8. hello: {
  9. type: GraphQLString,
  10. }
  11. })
  12. });

简单分析一下上面的代码,可以看到 HelloWorldType 是一个 GraphQLObjectType 的实例,它包含一个 fields 是 hello,这个 hello 所对应的返回类型是字符串。

那如何返回 world 字符串?那就给它个 resolve 方法

</>复制代码

  1. const HelloWorldType = new GraphQLObjectType({
  2. name: "HelloWorldType",
  3. fields: () => ({
  4. hello: {
  5. type: GraphQLString,
  6. resolve() {
  7. return "world";
  8. },
  9. }
  10. })
  11. });

这样类型就定义好了,还记不记得上篇文章提到的类型定义完成后该怎么办?

对,创建查询的 schema。

</>复制代码

  1. import {
  2. GraphQLString,
  3. GraphQLObjectType,
  4. GraphQLSchema,
  5. } from "graphql";
  6. const HelloWorldType = new GraphQLObjectType({
  7. name: "HelloWorldType",
  8. fields: {
  9. hello: {
  10. type: GraphQLString,
  11. resolve() {
  12. return "world";
  13. },
  14. }
  15. }
  16. });
  17. const schema = new GraphQLSchema({
  18. query: HelloWorldType
  19. });

schema 设置好了,是不是想查询看看哪?

东风当然是服务器啦。GraphQL 官方提供 express-graphql 这个中间件来支持基于 GraphQL 的查询,所以,这里选用 Express 作为服务器。

安装就不再重复了,只需将刚刚建立的 schema 添加到 express 的中间件中就可以了。

</>复制代码

  1. const app = express();
  2. app
  3. .use("/graphql", graphqlHTTP({ schema, pretty: true }))
  4. .listen(3000, () => {
  5. console.log("GraphQL server running on http://localhost:3000/graphql");
  6. });

当当当当~完成,去 Postman 里查询 http://localhost:3000/graphql?query={hello} 看看吧。

Blog System

在上一篇文章里,我们设计了一个博客的查询 schema,这次我们就来动手实现它。(下面就开始讲例子啦,不愿听我唠叨的可以直接看代码)

前面 HelloWorld 的例子讲的比较详细,现在大家熟悉了语法,接下来的案例就会过得快一些。

首先是 PostType,这里对 Posttype 做了一点小修改,给几个字段添加了不能为空的设计。

</>复制代码

  1. /**
  2. * type Post {
  3. * id: ID!,
  4. * name: String!,
  5. * createDate: String!,
  6. * title: String!,
  7. * subtitle: String,
  8. * content: String,
  9. * tags: [Tag]
  10. * }
  11. */
  12. const Post = new GraphQLObjectType({
  13. name: "PostType",
  14. fields: () => ({
  15. id: {
  16. type: new GraphQLNonNull(GraphQLID)
  17. },
  18. name: {
  19. type: new GraphQLNonNull(GraphQLString)
  20. },
  21. createDate: {
  22. type: new GraphQLNonNull(GraphQLString)
  23. },
  24. title: {
  25. type: new GraphQLNonNull(GraphQLString)
  26. },
  27. subtitle: {
  28. type: GraphQLString
  29. },
  30. content: {
  31. type: GraphQLString
  32. },
  33. tags: {
  34. type: new GraphQLList(TagType),
  35. resolve: post => post.tags.map(tagName => getTagByName(tagName))
  36. }
  37. })
  38. });

然后是另一个主要的 type: Tag type。

</>复制代码

  1. /**
  2. * type Tag {
  3. * id: ID!,
  4. * name: String!,
  5. * label: String!,
  6. * createDate: String!,
  7. * posts: [Post]
  8. * }
  9. */
  10. const Tag = new GraphQLObjectType({
  11. name: "TagType",
  12. fields: () => ({
  13. id: {
  14. type: new GraphQLNonNull(GraphQLID)
  15. },
  16. name: {
  17. type: new GraphQLNonNull(GraphQLString)
  18. },
  19. label: {
  20. type: new GraphQLNonNull(GraphQLString)
  21. },
  22. createDate: {
  23. type: new GraphQLNonNull(GraphQLString)
  24. },
  25. posts: {
  26. type: new GraphQLList(PostType),
  27. resolve: tag => getPostsList().filter(post => ~post.tags.indexOf(tag.name))
  28. }
  29. })
  30. });

两个主要的类型已经定义好了,把它们俩整合起来就是博客类型了。

</>复制代码

  1. /**
  2. * type Blog {
  3. * post: Post, // 查询一篇文章
  4. * posts: [Post], // 查询一组文章,用于博客首页
  5. * tag: Tag, // 查询一个标签
  6. * tags: [Tag], // 查询所有标签,用于博客标签页
  7. * }
  8. */
  9. const BlogType = new GraphQLObjectType({
  10. name: "BlogType",
  11. fields: () => ({
  12. post: {
  13. type: PostType,
  14. args: {
  15. name: {
  16. type: GraphQLString
  17. }
  18. },
  19. resolve: (blog, { name }) => getPostByName(name),
  20. },
  21. posts: {
  22. type: new GraphQLList(PostType),
  23. resolve: () => getPostsList(),
  24. },
  25. tag: {
  26. type: TagType,
  27. args: {
  28. name: {
  29. type: GraphQLString
  30. }
  31. },
  32. resolve: (blog, { name }) => getTagByName(name),
  33. },
  34. tags: {
  35. type: new GraphQLList(TagType),
  36. resolve: () => getTagsList(),
  37. }
  38. })
  39. });

这里有一个新东西,就是 arg 字段,用来获取查询参数,如果在没有设置过 arg 字段的属性上添加变量进行查询,graphql-js 的验证系统会报错。

最后,将之前的 helloworld 类型稍微修饰一下,独立出来,然后和 blog type 整合到一起成为根查询类。

</>复制代码

  1. const queryType = new GraphQLObjectType({
  2. name: "RootQueryType",
  3. fields: () => ({
  4. hello: WorldType,
  5. blog: {
  6. type: BlogType,
  7. resolve: () => ({})
  8. },
  9. })
  10. });
  11. const schema = new GraphQLSchema({
  12. query: queryType
  13. });

OK。这样整个 Demo 就完成了(查看源码戳这里),快去 Postman 试试各种查询,体验 GraphQL 的神奇吧。(不知道怎么写查询语句的就看上一篇吧)

最后

如果,你不喜欢 GET 方法或查询字符串过长,express-graphql 也支持 POST 方法,服务器会先查看请求的 URL 中是否包含查询字符串,如果不包含就会去 request body 中获取,只需在 request header 中将 Content-Type 设置为 application/graphql 就可以了。

全文一直在说查询,或许你会疑惑,那我修改怎么做哪?graphql 中的修改称之为 mutationmutation 可以定义自己的接口解析类,它在 graphql 的 schema 中是一个可选项,其他的和查询并无两样,只是最后在 resolve 方法中的处理方式不同而已。

</>复制代码

  1. const schema = new GraphQLSchema({
  2. query: queryType,
  3. mutation: mutationType
  4. });

最后的最后提一句,nodemon 很好用,谁用谁知道。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/91643.html

相关文章

  • GraphQL 核心概念

    摘要:系列文章核心概念本文浅尝最近因为工作上新产品的需要,让我有机会了解和尝试。这篇文章主要分享的是的核心概念,主要分为和四部分。再次强调,本文主要讲的是的核心概念,中所定义的类,都是设计类,并不是具体实现代码。 A query language created by Facebook for describing data requirements on complex applicati...

    LancerComet 评论0 收藏0
  • Facebook--Graphql 为什么功能这么强大?与开源数据库的结合分析

    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...

    gclove 评论0 收藏0
  • Facebook--Graphql 为什么功能这么强大?与开源数据库的结合分析

    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...

    894974231 评论0 收藏0
  • Facebook--Graphql 为什么功能这么强大?与开源数据库的结合分析

    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...

    Seay 评论0 收藏0
  • 浅尝正则表达式

    摘要:同样的你也可以测试第四次执行的时候就会是了,需要知道的是,只有在全局检索时才会生效,否则的话只会返回哦方法二使用正则表达式模式对字符串执行搜索,并将更新全局对象的属性以反映匹配结果。 之前写正则都是各种上网搜索,还是没有系统的学习过正则表达式的用法,今天稍稍研究了一下下,感觉还是收获颇丰的,分享给各位,希望对于你们有所帮助~~ 修饰符 g --全局匹配 i --不区分大小写,默认...

    HelKyle 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<