知海

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:下一个中间件,或者最终被包裹的解析器。
  • rootargscontextinfo:标准 GraphQL 解析器参数。

你可以在中间件中:

  1. 在调用 resolve 前执行预处理逻辑(如日志、鉴权、参数校验)。
  2. 调用 await resolve(root, args, context, info) 获得解析结果。
  3. 在解析完成后处理结果或异常,并返回(或修改)结果。

使用示例

下面使用 Apollo Server 和 @graphql-tools/schema,演示如何用中间件为 Query.helloQuery.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 添加横切关注点。

帮助我们改进文档

发现翻译问题或内容错误?请告诉我们。