koa + graphql + dataloader
·2 mins
Table of Contents
如果不熟悉 dataloader 和 graphql,请看之前的两篇文章。
dataloader 配合 graphql 使用会使得 schema 定义变得非常简洁清晰。
定义 dataloader 服务 #
首先需要定义一个 koa-graphql 服务,和之前文章的有些许不同, 之前是使用一个 object 当做数据 store 存在内存, 这次我们使用 sqlite 数据库。
const schema = require('./schema')
const { user, post } = require('./dataloader')
const app = new Koa()
const router = new Router()
app.use(bodyParser())
router.get('/graphql', graphiqlKoa({ endpointURL: '/graphql' }))
router.post(
'/graphql',
graphqlKoa({
schema,
// 上下文,所有的resolver均可拿到
context: {
user,
post,
},
})
)
app.use(router.routes())
app.listen(3000, () => console.log(`listening on port 3000`))
将 dataloader 实例传入上下文,可供 resolver 使用,如果不使用 dataloader 也可以传入 db model。
定义 schema #
// schema.js
const { makeExecutableSchema } = require('graphql-tools')
const rootSchema = [
`
type User {
id: Int
username: String
}
type Post {
id: Int,
title: String,
author_id: Int,
author: User
}
type Query {
user(id: Int!): User
post(id: Int!): Post
}
`,
]
const rootResolvers = {
Query: {
// 参数1为前一个对象,此处为Query, 参数2为查询输入参数, 参数3为自定义上下文对象
user: (_, { id }, { user }) => user.load(id),
// resolver 需要返回一个包含schema定义字段的object或者返回此object的promise函数
post: (_, { id }, { post }) => post.load(id),
},
Post: {
// 此处定义Post的author字段的resolver,参数1为Post,根据post的author_id得到author信息,
// 由于这条查询会在查询post的author字段时自动触发,所以没有用户查询输入参数
author: ({ author_id }, _, { user }) => user.load(author_id),
},
}
module.exports = makeExecutableSchema({
typeDefs: rootSchema,
resolvers: rootResolvers,
})
可以看到使用 dataloader 可以将数据查询逻辑放在 dataloader 中,使得 schema 非常简洁清晰。
使用 #
启动服务,打开http://localhost:3000/graphql, 输入:
{
user(id: 15) {
id
username
}
post(id: 2) {
id
title
author_id
author{
id
username
}
}
}
可得到结果
{
"data": {
"user": {
"id": 15,
"username": "Tate Heaney"
},
"post": {
"id": 2,
"title": "Eum voluptates nulla alias alias excepturi",
"author_id": 15,
"author": {
"id": 15,
"username": "Tate Heaney"
}
}
}
}
完整代码,请看http://gost.surge.sh/#/gost/99cd47c0-9ad5-409e-9456-0d9e74e19495