一种用于 API 的查询语言。
GraphQL 既是一种用于 API 的查询语言也是一个满足你数据查询的运行时。 GraphQL 对你的 API 中的数据提供了一套易于理解的完整描述,使得客户端能够准确地获得它需要的数据,而且没有任何冗余,也让 API 更容易地随着时间推移而演进,还能用于构建强大的开发者工具。
对比 restful api:
restful —个接口只能返回一个资源, graphql 一次可以获取多个资源。
restful 用不同的 url 来区分资源, graphql 用类型区分资源。
安装使用 JavaScript 语言,express node.js 框架开始。
npm install express express-graphql graphql创建 server.js 并 使用命令 node server.js 运行 demo。
const express = require('express'); const app = express(); const { graphqlHTTP } = require('express-graphql'); const { buildSchema } = require('graphql'); const schema = buildSchema(` type Query { hello: String } `); const root = { hello: () => 'Hello world!' }; app.use('/graphql', graphqlHTTP({ schema: schema, rootValue: root, graphiql: true, })); app.listen(4000, () => console.log('Now browse to localhost:4000/graphql')); 参数类型基本类型: String, Int, Float, Boolean, ID。
[类型]代表数组,例如:[Int]代表整型数组。
参数传递和 JavaScript 传递参数一样,小括号内定义形参,但是注意 : 参数需要定义类型。
! 叹号代表参数不能为空。
type Query { rollDice (numDice: Int!, numSide: Int): [Int] } 自定义参数类型GraphQL 允许用户自定义参数类型,通常用来描述要获取的资源的属性。
type Account { name: String age: Int sex: String department: String salary: (city: String): Int } type Query { account (name: string): Account }server.js
const schema = buildSchema(` type Account { name: String age: Int sex: String department: String salary(city: String): Int } type Query { hello: String getClassMates(classNo: Int!): [String] account (username: String): Account } `) const root = { hello: () => 'Hello world!', getClassMates: ({ classNo }) => { const obj = { 31: ['张三', '李四', '王五'], 61: ['张大三', '李大四', '王大五'], } return obj[classNo] }, account: ({ username }) => { const name = username const sex = 'nan' const age = 10 const department = '开发部' const salary = ({ city }) => { if (city === '北京' || city === '上海' || city === '深圳' || city === '广州') { return 10000 } return 3000 } return { name, sex, age, department, salary, } }, } 在客户端访问GraphQL接口在 server.js 公开文件夹 供用户访问静态资源。
app.use(express.static('public'))index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <button>获取数据</button> <script> function getData() { const query = ` query Account ($username: String!) { account(username: $username) { name age sex salary(city: "北京") } }` const variables = { username: '李大四' } fetch('/graphql', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' }, body: JSON.stringify({ query, variables }) }) .then(res => res.json) .then(json => { console.log(json) }) } </script> </body> </html>后端的 username 对应 variales 的值中的 username, 和 query 中的 $username。
使用 Mutations 修改数据不能单独使用 Mutation, 需结合 Query。
const schema = buildSchema(` type Account { name: String age: Int sex: String department: String salary(city: String): Int } input AccountInput { name: String age: Int sex: String department: String salary: Int } type Query { accounts: [Account] } type Mutation { createAccount(input: AccountInput): Account updateAccount(id: ID!, input: AccountInput): Account } `) // 模拟数据库 const fakeDb = {} const root = { createAccount({ input }) { // 模拟数据库保存 fakeDb[input.name] = input // 返回保存结果 return fakeDb[input.name] }, updateAccount({ id, input }) { // 模拟更新数据库 const updatedAccount = Object.assign({}, fakeDb[id], input) fakeDb[id] = updatedAccount return updatedAccount }, accounts() { let arr = [] for (const key in fakeDb) { arr.push(fakeDb[key]) } return arr }, }试着创建一个 account。
通过 accounts,查询到刚刚创建的 account。
试着修改数据,我们将 age 18 改为 20,并将该 account 更改后的信息返回。
这里将 name 作为记录的主键了。
Constructing Types上文通过字符串的形式构建 schema,还可以通过构造函数来构建。