GraphQL
一、GraphQL
Facebook产品,跟React一样。
描述型的查询语言,可以把我们需要的资源全描述成类型。使用的时候我们可以只取得我们需要的字段。
非常方便的添加和废弃字段。
按需请求:后台给我提供我需要的字段
前端追求传输数据的Size。按需查询这样特别好。
二, GraphQL与restful对比
三、使用express+GraphQL
graphqlHTTP的参数对象接收三个字段,schema,rootValue和graphiql。我们需要写Schema和处理器。graphiql指定是否启用调试界面。
buildSchema定义查询语句的类型,我们对外公开的接口里面都有哪些查询方法,有哪些类型。
buildSchema的参数是一个字符串。
把执行权交给graphqlHTTP。
复杂类型,需要自定义类型。
他可以不请求,但是我需要都返回。
遇到问题,Document一直load不出来,query也出不来提示Query root type must be provided.
原因:定义schema的时候类型Query一定要大写,我写成小写了。
四、参数类型和参数传递
GraphQL中基本类型有5种。ID类型,不能重复。
声明参数类型
五,GraphQL Client
可以看到username是怎样传递给$username的。
客户端传递的query是一个字符串。
这里的query跟我们调试的时候的query一样。
子字段也可以接受参数,可以通过外面传入。
六,使用Mutations修改数据
Mutation的英文意思就是修改,变更
输入类型用input定义, input AccountInput
查询类型用type定义。type Account
id: ID!表示id不能为空
定义mutation, 定义输入类型input AccountInput。查询类型Account。
对于GraphQL来说,必须有一个query。
Input类型
七,认证和中间件
用express框架的中间件,注册中间件
请求/graphql,且请求中有headers,headers中的cookie中没有auth,认为没有权限,返回错误并return终止处理。
const middleware = (req, res, next)=>{ if(req?.url?.indexOf("/graphql") !== -1 && (req.headers.cookie===undefined || req.headers.cookie?.indexOf("auth") === -1)){ res.send(JSON.stringify({ error: "您没有权限访问这个接口" })); return; } next(); } //注册中间件 app.use(middleware);
实际开发中,服务器会生成token给前端,前端请求再带回来,服务器验证token。
八、Constructing Types
构造类型,带来我们编程方式的改变。
把类型的定义变成了构造函数。
借助GraphQLObjectType构造函数里面来定义。
代码量上升带来的好处,便于维护。
过去buildSchema一句话完成的事分成了三步,
完整代码
const express = require('express'); const {buildSchema, graphql, GraphQLSchema, GraphQLObjectType, GraphQLString, GraphQLInt} = require('graphql'); const {graphqlHTTP} = require('express-graphql'); //第一步,定义类型 var AccountType = new GraphQLObjectType({ name:"Account", fields:{ name:{type: GraphQLString}, age:{type:GraphQLInt}, sex:{type:GraphQLString}, department:{type:GraphQLString} } }) //第二步,定义查询 var queryType = new GraphQLObjectType({ name:"Query", fields:{ account:{ type:AccountType, args:{ userName: {type:GraphQLString} }, resolve: (_,{userName})=>{ const name = userName; const sex='man'; const age=18; const department='开发部'; const salary = ({city})=>{ if(city==='北京'|| city ==='上海'|| city==='广州'||city==='深圳'){ return 10000; }else{ return 3000; } } return { //属性是无序的 name, sex, age, salary, department } } } } }) //第三步,创建Schema var schema = new GraphQLSchema({query: queryType}); const app = express(); app.use('/graphql', graphqlHTTP({ schema: schema, graphiql: true })) //公开文件夹,供用户访问静态资源 app.use(express.static('public')) app.listen(3000);
九,和db交互
const express = require('express'); const {buildSchema} = require('graphql'); const {graphqlHTTP} = require('express-graphql'); const mysql = require('mysql'); // https://www.npmjs.com/package/mysql var pool = mysql.createPool({ connectionLimit : 10, host : 'localhost', user : 'root', password : '123456', database : 'alice' }); //定义schema,定义查询和类型(查询方法), mutation const schema = buildSchema(` type Account{ name: String, age: Int, sex: String, department: String } input AccountInput{ name: String, age: Int, sex: String, department: String } type Mutation{ createAccount(input:AccountInput):Account updateAccount(id:ID!, input:AccountInput):Account, deleteAccount(id:ID!):Boolean } type Query{ accounts: [Account] } `); //定义查询对应的处理器 const root = { createAccount: ({input})=>{ const data = { name: input.name, sex: input.sex, age: input.age, department: input.department } return new Promise((resolve, reject)=>{ pool.query('insert into account set ?', data, (err)=>{ if(err){ console.log("出错了",err); return; } resolve(data); }) }); }, updateAccount:({id,input})=>{ const data = input; return new Promise((resolve, reject)=>{ pool.query('update account set ? where name=?', [data,id], (err)=>{ if(err){ console.log("出错了",err); return; } resolve(data); }) }); }, accounts:()=>{ return new Promise((resolve, reject)=>{ pool.query('select name, age, sex, department from account',(err, results)=>{ if(err){ console.log("出错了",err); return; } const arr = []; for(let i =0; i<results.length;i++){ arr.push({ name:results[i].name, age:results[i].age, sex:results[i].sex, department:results[i].department }) } resolve(arr); }) }) }, deleteAccount:({id})=>{ return new Promise((resolve, reject)=>{ console.log(id); pool.query('delete from account where name= ?',[id],(err)=>{ if(err){ console.log("出错了",err); reject(false); return; } resolve(true); }) }); } } const app = express(); app.use('/graphql', graphqlHTTP({ schema: schema, rootValue: root, graphiql: true })) //公开文件夹,供用户访问静态资源 app.use(express.static('public')) app.listen(3000);
源码:
https://github.com/starof/qianfeng-graphql
如果觉得本文对您有帮助~可以
微信支持一下:![微信打赏](http://files.cnblogs.com/files/starof/starof_wx.bmp)