GraphQL的JavaScript实现graphql-js应用举例
系列文章:
GraphQL 核心概念 graphql-js 浅尝(本文)常言道,实践是检验真理的唯一标准。
上一篇文章讲了 GraphQL 的核心概念,所提到的一些例子都是理论化的,并没有实际代码做支撑,就好像在画一个大饼,总是让人不那么信服。
它真的有那么神奇吗?那就同我一起看下去,用事实说话。
之前那篇文章一直有提到 GraphQL 是一个概念,每个语言可以有自己实现它的方式。因为,我是搞前端的,对 JavaScript 比较熟悉,所以,这里就用 graphql-js(GraphQL 的 JavaScript 实现)来举例。
Hello World
遵循传统,第一个例子必须是 Hello World。
首先,安装就不用多说了。
npm install graphql-js --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(); .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
利用JavaScript实现二级联动 利用JavaScript实现二级联动 要实现JavaScript二级联动效果,首先要确定需要哪些技术: 二维数组 for in循环 new Option(text,value,true,true) add(option,null) onchange() 表单事件 HTML代码: !-- input type= text id= text -- 请选择省份: select name= id= provinces !-- option value= 江苏省 江苏省 /option
相关文章
- JavaScript_DOM
- 从 prototype.js 深入学习 javascript 的面向对象特性
- Javascript将字符串日期格式化为yyyy-mm-dd的方法 js number 类型 没有length 属性 string类型才有
- 【JavaScript】JS最简单的二级折叠菜单的实现方法(完整实例)
- 【JavaScript】JS的启动机制
- 一篇文章把你带入到JavaScript中的闭包与高级函数
- JavaScript-求时间差
- JavaScript 模拟键盘事件
- 《21天学通HTML+CSS+JavaScript Web开发(第7版)》——2.7 小结
- JS教程之什么是 JavaScript 闭包?
- Selenium2学习-036-WebUI自动化实战实例-034-JavaScript 在 Selenium 自动化中的应用实例之六(获取 JS 执行结果返回值)
- 微信小程序开发规范文档-JavaScript语言规范
- javascript: detect mobile devices or browser
- JavaScript 闭包
- TypeScript和JavaScript的区别,全面解读超详细
- JavaScript Html与JS基于事件实现交互
- JS: javascript 点击事件执行两次js问题 ,解决jquery绑定click事件出现点击一次执行两次问题
- [js高手之路] javascript面向对象写法与应用
- [js高手之路]javascript腾讯面试题学习封装一个简易的异步队列
- JS-安全检测JavaScript基本数据类型和内置对象的方法
- 华为OD机试 - 和最大子矩阵(JavaScript) | 机试题+算法思路+考点+代码解析 【2023】
- 轻松学习JavaScript十二:JavaScript基于面向对象之创建对象(一)
- Atititjs javascript异常处理机制java异常转换.js exception process
- lzugis——Arcgis Server for JavaScript API在自己的定义InfoWindow
- 数据交换格式(XML与JSON)、JSON与JavaScript对象之间互转
- js 手机端触发事事件、javascript手机端/移动端触发事件
- javascript Date format(js日期格式化)(转)
- JavaScript实战代码复制,包含JS这种场景
- 比较有意思的原生态js拖拽写法----摘自javascript高级程序设计3