系列文章:GraphQL核心概念graphql-js品味(本文)俗话说,实践是检验真理的唯一标准。上一篇文章讲了GraphQL的核心概念。提到的一些示例是理论上的,不受实际代码支持。就像画了一个大饼,总是没有说服力。真的有那么神奇吗?那就跟我一起看,用事实说话。上一篇一直提到GraphQL是一个概念,每种语言都可以有自己的实现方式。由于本人从事前端工作,熟悉JavaScript,所以这里以graphql-js(GraphQL的JavaScript实现)为例。HelloWorld遵循传统,第一个例子必须是HelloWorld。首先,安装就不用多说了。npminstallgraphql-js--save这个例子应该怎么设计?假设,如果您查询一个hello字符串,您将返回一个world字符串。很明显,type的结构应该是这样的:typeHelloWorld{hello:String}这个HelloWorld类型如何实现呢??graphql-js已经定义了基础类,我们直接调用即可。然后,这个类型实现起来就很简单了});简单分析上面的代码,可以看到HelloWorldType是GraphQLObjectType的一个实例,其中包含一个字段hello,hello对应的返回类型是一个字符串。那怎么返回world字符串呢?然后给它一个resolve方法constHelloWorldType=newGraphQLObjectType({name:'HelloWorldType',fields:()=>({hello:{type:GraphQLString,resolve(){return'world';},}})});这样,类型就定义好了。还记得上一篇文章中提到的类型定义完成后要做什么吗?是的,创建一个查询模式。import{GraphQLString,GraphQLObjectType,GraphQLSchema,}from'graphql';constHelloWorldType=newGraphQLObjectType({name:'HelloWorldType',fields:{hello:{type:GraphQLString,resolve(){return'world';},}}});constschema=newGraphQLSchema({query:HelloWorldType});架构已设置,是否要查询?东风当然是服务器。GraphQL官方提供了express-graphql中间件来支持基于GraphQL的查询,所以这里选择Express作为服务端。不再重复安装,直接将刚刚创建的schema添加到express中间件即可。constapp=express();app.use('/graphql',graphqlHTTP({schema,pretty:true})).listen(3000,()=>{console.log('GraphQLserverrunningonhttp://localhost:3000/graphql');});当当当当当~大功告成,去Postman查询http://localhost:3000/graphql?query={hello}就可以看到了。博客系统在上一篇文章中,我们设计了一个博客查询模式,这次我们将手动实现它。(下面是例子,不想听我唠叨的可以直接看代码)前面的HelloWorld例子比较详细。既然大家都熟悉了语法,下面的案例就会通过得更快。第一个是PostType。这里对Posttype做了一个小小的修改,在几个字段中加入了不能为空的设计。/***typePost{*id:ID!,*name:String!,*createDate:String!,*title:String!,*subtitle:String,*content:String,*tags:[标签]*}*/constPost=newGraphQLObjectType({name:'PostType',fields:()=>({id:{type:newGraphQLNonNull(GraphQLID)},name:{type:newGraphQLNonNull(GraphQLString)},createDate:{type:newGraphQLNonNull(GraphQLString)},标题:{type:newGraphQLNonNull(GraphQLString)},副标题:{type:GraphQLString},内容:{type:GraphQLString},标签:{type:newGraphQLList(TagType),resolve:post=>post.tags.map(tagName=>getTagByName(tagName))}})});然后还有另外一个主要类型:Tag类型。/***typeTag{*id:ID!,*name:String!,*label:String!,*createDate:String!,*posts:[Post]*}*/constTag=newGraphQLObjectType({name:'TagType',字段:()=>({id:{type:newGraphQLNonNull(GraphQLID)},名称:{type:newGraphQLNonNull(GraphQLString)},标签:{type:newGraphQLNonNull(GraphQLString)},createDate:{type:newGraphQLNonNull(GraphQLString)))},posts:{type:newGraphQLList(PostType),resolve:tag=>getPostsList().filter(post=>~post.tags.indexOf(tag.name))}})});两个主要的类型已经定义好了,将两者结合起来就是博客的类型。/***typeBlog{*post:Post,//查询一篇文章*posts:[Post],//查询博客首页的一组文章*tag:Tag,//查询一个标签*tags:[Tag],//查询所有标签,用于博客标签页*}*/constBlogType=newGraphQLObjectType({name:'BlogType',fields:()=>({post:{type:PostType,args:{name:{type:GraphQLString}},resolve:(blog,{name})=>getPostByName(name),},posts:{type:newGraphQLList(PostType),resolve:()=>getPostsList(),},tag:{type:TagType,args:{name:{type:GraphQLString}},resolve:(blog,{name})=>getTagByName(name),},tags:{type:newGraphQLList(TagType),resolve:()=>getTagsList(),}})});这里有一个新东西,就是arg字段,用来获取查询参数。如果在arg字段没有设置的属性中添加变量进行查询,graphql-js的验证系统会报错。***,稍微修改之前的helloworld类型,将其分离,然后与blog类型整合成为根查询类。constqueryType=newGraphQLObjectType({name:'RootQueryType',fields:()=>({hello:WorldType,blog:{type:BlogType,resolve:()=>({})},})});constschema=newGraphQLSchema({query:queryType});好的。这样,整个Demo就完成了(点此查看源码),去Postman中尝试各种查询,体验GraphQL的神奇。(如果你不知道怎么写查询语句,看之前的文章)***如果你不喜欢GET方式或者查询字符串太长,express-graphql也支持POST方式,并且服务器会先检查请求的URL是否包含查询字符串,如果不包含,则从请求体中获取。只需在请求标头中将Content-Type设置为application/graphql即可。全文一直在说疑问,大家可能会疑惑,我应该怎么修改呢?graphql中的修改称为突变。Mutation可以定义自己的接口解析类,这是graphqlschema中的一个option,其他和queries一样,只是在resolve方法中对***的处理不同。constschema=newGraphQLSchema({query:queryType,mutation:mutationType});*******顺便提一下,nodemon非常好用,用过的人都知道。
