1.请求需要的数据,不多不少
例如:account中有name,age,sex,department等,可以只取得需要的字段。
2.获取多个资源,只用一个请求
3.描述所有可能类型的系统。便于维护,根据需求平滑演进,添加或者隐藏字段。
例如一个查询请求:
//GraphQL语法,后面会讲到
//会根据字段进行数据的获取,而不像REST直接将所有的字段进行返回,这是一个特别好的前端优化的点
query{
getAccount(userId:1){
name //graphql语法会根据里面的字段取出对应的值
age
sex
}
}
结果如下:
{
“data”:{
"getAccount":{
"name":"xxx",
"age":"xxx",
"sex":"xxx"
}
}
}
const express = require('express');
const graphqlHTTP = require('express-graphql');
const {buildSchema} = require('graphql');
//Construct a schema,using GraphQL,schema language
//构建schema,这定义查询的语句和类型
const schema= buildSchema(
type Account{
name:String
age:Int
sex:String
}
type Query{
hello:String
accountName:String
account:Account
}
);
//The root proyides a resolver function for each API
//定义查询所对应的resolver,也就是查询对应的处理器
const root={
hello:()=>{
return 'Hello World!';
},
accountName:()=>{
return "test name";
};
account:()=>{
return {
name:"test name",
age:11,
sex:"test sex",
}
}
};
const app = express();
app.use('/graphql',graphqlHTTP({
schema:schema,
rootValue:root,
graphql:true, //是否启用调试界面,false就不能调试了,开发时是true,上线的话变为false
}))
app.listen(4000);
type Query{
rollDice(numDice:Int!,numSides:Int):[Int]
}
type Account{
name:String
age:Int
sex:String
salary(city:String):Int
}
type Query{
account(name:String):Account //定义一个Account属性,然后在Account类型中进行返回
}
var username = 66;
//固定写法,Account($username:Int!),account(username:$username),$username和后端的username是一样的
var query = `query Account($username:Int!){
account(username:$username)
}`;
fetch('/graphql',{
method:'POST',
headers:{
'Content-Type':'application/json',
'Accept':'application/json',
},
//因为是post,数据从body出去
body:JSON.stringify({
query,
variables:{username},
})
})
.then(r=>r.json())
.then(data=>console.log('data returned',data));
后端代码
const express = require('express');
const {buildSchema} = require('graphql');
const graphql = require('express-graphql');
//定义schema,查询和类型
const schema = buildSchema(`
type Account{
name:String
age:Int
sex:String
department:String
salary(city:String):Int
}
type Query{
getClassMates(classNo:Int!):[String]
account(username:String):Account
}
`)
//定义查询对应的处理器
const root={
getClassMates({classNo}){
const obj={
31:['name1','name2','name3'],
32:['name4','name5','name6']
}
return obj[classNo];
},
account({username}){
const name=username;
const sex='man';
const age=11;
const department='testdepartment';
const salary=({city})=>{
if(city==='北京'||city==='上海'||city==='广中'||city==='深圳'){
return 10000;
}
return 2000;
}
return {
name,
sex,
age,
department,
salary
}
}
}
const app=express();
app.use('/graphql',graphqlHTTP({
schema:schema,
rootValue:root,
graphiql:true
}))
//公开文件夹,供用户访问静态资源
app.use(express.static("public")
app.listen(3000);
前端代码
Document
//input表示输入
input AccountInput{
name:String
age:Int
sex:String
department:String
salary:Int
}
type Mutation{
//括号里是形参
createAccount(input:AccountInput):Account
updateAccount(id:ID!,input:AccountInput):Account
}
代码
小坑:
const express = require('express');
const {buildSchema}=require('graphql');
const graphqlHTTP=require('express-graphql');
//定义schema,查询和类型,mutation
const schema=buildSchema(`
input AccountInput{
name:String
age:Int
sex:String
department:String
}
type Account{
name:String
age:Int
sex:String
department:String
}
type Mutation{
createAccount(input:AccountInput):Account
updateAccount(id:ID!,input:AccountInput):Account
}
type Query{
account:[Account]
}
`)
const fakeDB={};
//定义查询对应的处理器
const root={
account(){
var arr=[];
for(const key in fakeDB){
arr.push(fakeDB[key])
}
return arr;
},
createAccount({input}){
//相当于数据库的保存
fakeDB[input.name]=input;
//返回保存结果
return fakeDB[input.name];
},
updateAccount({id,input}){
//相当于数据库的更新
const updateAccount=Object.assign({},fakeDB[id],input);
fakeDB[id]=updateAccount;
//返回数据库
return updatedAccount;
}
}
const app=express();
app.use('/graphql',graphqlHTTP({
schema:schema,
rootValue:root,
graphiql:true
}))
app.listen(3000)
const express = require('express');
const {buildSchema}=require('graphql');
const graphqlHTTP=require('express-graphql');
//定义schema,查询和类型,mutation
const schema=buildSchema(`
input AccountInput{
name:String
age:Int
sex:String
department:String
}
type Account{
name:String
age:Int
sex:String
department:String
}
type Mutation{
createAccount(input:AccountInput):Account
updateAccount(id:ID!,input:AccountInput):Account
}
type Query{
account:[Account]
}
`)
const fakeDB={};
//定义查询对应的处理器
const root={
account(){
var arr=[];
for(const key in fakeDB){
arr.push(fakeDB[key])
}
return arr;
},
createAccount({input}){
//相当于数据库的保存
fakeDB[input.name]=input;
//返回保存结果
return fakeDB[input.name];
},
updateAccount({id,input}){
//相当于数据库的更新
const updateAccount=Object.assign({},fakeDB[id],input);
fakeDB[id]=updateAccount;
//返回数据库
return updatedAccount;
}
}
const app=express();
//增加一个判断权限的中间件
const middleware=(req,res,next)=>{
if(req.url.indexOf('/graphql')!=-1&&req.headers.cookie.indexOf('auth')){
res.send(JSON.stringify({
error:"您没有权限访问这个接口"
}));
return;
}
next();
}
//使用中间件
app.use(middleware)
app.use('/graphql',graphqlHTTP({
schema:schema,
rootValue:root,
graphiql:true
}))
app.listen(3000)
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: 'root',
database: 'xxxx'
})
//定义schema,查询和类型,mutation
const schema = buildSchema(`
input AccountInput{
name:String
age:Int
sex:String
department:String
}
type Account{
name:String
age:Int
sex:String
department:String
}
type Mutation{
createAccount(input:AccountInput):Account
deleteAccount(id:ID):Boolean
updateAccount(id:ID!,input:AccountInput):Account
}
type Query{
account:[Account]
}
`)
const fakeDB = {};
//定义查询对应的处理器
const root = {
account() {
return new Promise((resolve,reject)=>{
pool.query('select name,age,sex,department from account',(err,results)=>{
if(err){
console.log('error',err.message);
return;
}
const arr=[];
for(const i=0;i {
pool.query('insert into accout set ?', data, (err) => {
if (err) {
console.log('error',err.message);
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',err.message);
return;
}
resolve(data);
})
})
},
deleteAccount({id}){
return new Promise((resolve,reject)=>{
pool.query('delete account where name=?',[id],(err)=>{
if(err){
console.log("err",err.message)
reject(false);
return;
}
resolve(true);
})
})
}
}
const app = express();
//增加一个判断权限的中间件
const middleware = (req, res, next) => {
if (req.url.indexOf('/graphql') != -1 && req.headers.cookie.indexOf('auth')) {
res.send(JSON.stringify({
error: "您没有权限访问这个接口"
}));
return;
}
next();
}
//使用中间件
app.use(middleware)
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true
}))
app.listen(3000)
学习视频:https://www.bilibili.com/video/av46200333?from=search&seid=9265460496338796424