GraphQL 是一种用于 API 的查询语言、也是一个知足你数据查询的运行时
是一种接口开发标准、支持常见的服务器开发语言
复制代码
建立服务端项目目录git
初始化项目 npm init -ygithub
建立入口文件 index.jsweb
安装依赖包数据库
Apollo-server-expressexpress
expressnpm
graphqljson
npm install apollo-server-express body-parser express graphql graphql-tools -S
复制代码
复制官方案例代码到index.js数组
启动bash
{
hello
}
复制代码
apolloserver 是一个实现了 GraphQL 规范的框架、能够基于apolloserver 快速开发基于 GraphQL 的服务端接口、而且方便客户端进行接口调用服务器
# 课程类型
type Course {
cname: String
score: Float
}
# 学生类型
type Student{
name: String
scores:[Course]
}
复制代码
type Query {
hello: String
# 定义字段参数 能够有默认值
stu(n: Int = 12): Student
}
# 获取参数(经过 resolver 函数的第二个参数获取客户端传递的参数数据)
const resolvers = {
Query: {
stu: (obj, args) => {
console.log(args)
}
}
}
# 客户端字段传递
{
stu(n: 13){
name
age
}
}
复制代码
内置类型中有两个特殊的类型:Query(主要用于查询操做) 和 Mutation(主要用于变动操做 -- 增、删、改 )
每个GraphQL 服务有一个 Query 类型、也可能有一个 mutation 类型、这两个类型本质上也是对象类型、惟一的区别就是他们做为客户端访问的入口
复制代码
enmu Fovour {
SWIMING
GODING
SINGING
}
复制代码
上述定义表示只能获取三种值之1、获取其余类型的值是不能够的
type Student{
name: String!
scores:[Score]!
}
复制代码
myField:[String!] 表示数组自己能够为空、可是其不能有任何空值成员
myField:[String]! 表示数组自己不能够为空、可是其能够包含空值成员
参数也能够是复杂类型、主要用于变动 mutation 场景 — 须要客户端传递输入类型
# 输入类型
input UserInfo{
name: String
pwd: String
}
#用户类型
type User {
id: ID
name: String
pwd: String
}
复制代码
定义 mutation、能够用于接收客户端传递的input类型数据
# 变动类型
type Mutation{
addUserByInput(userInput: UserInfo): User
}
复制代码
# 处理客户端传递的input参数
const resolvers = {
Query: {
hello: () => 'Hello world!'
},
Mutation: {
addUserByInput: (obj, args) => {
return {
id: uuid(),
name: args.userInput.name,
pwd: args.userInput.pwd
}
}
}
};
复制代码
# 客户端查询操做
mutation {
addUserByInput(userInput: {
name: 'nordon',
pwd: '123123'
}){
id
name
}
}
复制代码
###3.3.1 resolver 函数参数用法
resolvers 用于给类型字段提供实际数据
parent
上一级对象、若是字段属于根节点查询类型一般不会被使用args
能够提供在 GrapgQL 查询中传入的参数context
会被提供给全部解析器、而且持有重要的上下文信息。好比当前登入的用户、数据库访问对象info
一个保存与当前查询相关的字段特定信息以及 schema 详细信息的值Mutation: {
addUserByInput: (parent, args, context, info) => {
// parent 当前字段的父级对象 -- Query 中的 hello 至关于根节点,例如查学生中的 name、age 就是子节点
// args 客户端传递过来的参数
// context 能够用于操做数据源
// info 不怎么用
return {
id: uuid(),
name: args.userInput.name,
pwd: args.userInput.pwd
}
}
}
复制代码
// 类型定义
type Student {
name: String
age: Int
favour: String
}
// 数据解析
const resolvers = {
Student: {
// 提供字段的 resolver 函数、若是不提供会默认生成
name: (parent) => {
// return 'wangyao' 会覆盖父节点的 name
return parent.name
},
favour: (parent) => {
if(parent.favour === 'swimming'){
return '洗澡'
}else{
return parent.favour
}
}
},
Query: {
hello: () => 'Hello world!',
stu: (parent) => {
return {
name: 'nordon',
age: 18,
favour: 'swimming'
}
}
},
};
复制代码
经过 context 函数更加方便的对接数据源(数据库、文件、第三方接口)、包括异步操做
// context 能够用于获取数据源对象
const context = () => {
return {
db: 'dbObj'
}
}
const server = new ApolloServer({
typeDefs,
resolvers,
context
})
复制代码
// 在 resolver 函数中能够经过 context 对象操做数据源
const resolvers = {
Query: {
hello: (parent, args, context) => {
// 经过 context 能够获取数据源操做对象
let ret = context.db
}
}
}
复制代码
// db.js 代码:从文件中读取数据、本质上与从数据库中读取数据类型、多能够异步操做
const path = require('path')
const fs = require('fs')
module.exports.getData = () => {
const dataPath = path.join(__dirname, 'data.json')
return new Promise((resolve, reject) => {
fs.readFile(dataPage, (err, data) => {
if(err){
reject(err)
}
resolve(data.toString())
})
})
}
// data.json 提供数据源
[{
"name": "nordon",
"age": 18
},{
"name": "wangyao",
"age": 22
},{
"name": "bing",
"age": 23
}]
复制代码
// 从文件中读取数据做为数据源、 db.getData() 返回 Promise 实例对象
const db = require('./db.js')
const typeDefs = gql`
# 学生
type Student {
name: String
age: Int
}
# 查询类型
type Query {
hello: [Student!]!
}
`;
const context = ({req}) => {
return {
db: db
}
}
const resolvers = {
Query: {
hello: async (parent, args, context, info) => {
const ret = await context.db.getData()
return JSON.parse(ret)
}
}
}
const server = new ApolloServer({
typeDefs,
resolvers,
context
})
复制代码