JavaScript:GraphQL Middleware(中间件)
graphql-github-io-zh-Hans生态项目与库
JavaScript:GraphQL Middleware(中间件)
GraphQL Middleware 是一个 schema 包装器,可让你将 GraphQL 解析器拆分成一系列中间件函数,从而更高效地在多个解析器之间管理附加功能。通过组合中间件,你可以轻松地在解析器执行前(before)和执行后(after)插入公共逻辑,避免在每一个解析器中重复样板代码。
项目地址:https://github.com/maticzav/graphql-middleware
npm 包名:graphql-middleware
功能特性
- 💡 易用:直观而熟悉的 API,可以快速上手。
- 💪 强大:允许完全控制解析器,在解析器执行前和执行后挂载逻辑。
- 🌈 兼容:适用于任意 GraphQL Schema。
安装
bash
npm install graphql-middleware
中间件概念
中间件是一个形如 async (resolve, root, args, context, info) => ... 的函数:
resolve:下一个中间件,或者最终被包裹的解析器。root、args、context、info:标准 GraphQL 解析器参数。
你可以在中间件中:
- 在调用
resolve前执行预处理逻辑(如日志、鉴权、参数校验)。 - 调用
await resolve(root, args, context, info)获得解析结果。 - 在解析完成后处理结果或异常,并返回(或修改)结果。
使用示例
下面使用 Apollo Server 和 @graphql-tools/schema,演示如何用中间件为 Query.hello 与 Query.bye 添加统一日志。示例代码中使用了中间件组合函数 applyMiddleware:
ts
const { ApolloServer } = require('apollo-server')
const { makeExecutableSchema } = require('@graphql-tools/schema')
const { applyMiddleware } = require('graphql-middleware')
const typeDefs = `
type Query {
hello(name: String): String
bye(name: String): String
}
`
const resolvers = {
Query: {
hello: (root, args, context, info) => {
console.log(`3. resolver: hello`)
return `Hello ${args.name ? args.name : 'world'}!`
},
bye: (root, args, context, info) => {
console.log(`3. resolver: bye`)
return `Bye ${args.name ? args.name : 'world'}!`
},
},
}
const logInput = async (resolve, root, args, context, info) => {
console.log(`1. logInput: ${JSON.stringify(args)}`)
const result = await resolve(root, args, context, info)
console.log(`5. logInput`)
return result
}
const logResult = async (resolve, root, args, context, info) => {
console.log(`2. logResult`)
const result = await resolve(root, args, context, info)
console.log(`4. logResult: ${JSON.stringify(result)}`)
return result
}
const schema = makeExecutableSchema({ typeDefs, resolvers })
const schemaWithMiddleware = applyMiddleware(schema, logInput, logResult)
const server = new ApolloServer({
schema: schemaWithMiddleware,
})
await server.listen({ port: 8008 })
注意:示例代码使用了顶层 await,实际运行时可将其包裹在
async函数中。
当客户端发送请求 { hello(name: "world") } 时,控制台会按“洋葱模型”输出以下顺序:
1. logInput: {"name":"world"}
2. logResult
3. resolver: hello
4. logResult: "Hello world!"
5. logInput
可以看到,多个中间件按传入顺序包裹解析器:logInput 先执行前置逻辑,然后进入 logResult,最后到达真正的解析器;返回阶段则按相反顺序依次执行后置逻辑。这使得你可以在不修改解析器代码的前提下,灵活地为 GraphQL API 添加横切关注点。
帮助我们改进文档
发现翻译问题或内容错误?请告诉我们。
