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
})
複製代碼