掘金 后端 ( ) • 2024-04-07 10:18

在GraphQL中,context是一个在所有解析器之间共享的对象,它携带了在处理一个特定请求时可能需要的跨解析器的信息。这允许您在整个请求期间传递信息和依赖项,例如用户认证信息、数据库连接或其他服务。

作用和好处

  1. 跨解析器共享数据context可以在所有解析器间共享数据,这对于需要在多个解析器中访问相同信息的情况非常有用。
  2. 隔离请求特定的信息:每个请求都会生成一个新的context对象,因此它适合存储请求特定的信息(如当前登录的用户)。
  3. 安全性和隔离:使用context来传递信息更安全,因为它避免了全局状态,并且可以隔离不同请求的数据。

代码示例

假设您有一个GraphQL服务,需要访问数据库并知道当前的用户。以下是一个如何设置和使用context的示例:

设置GraphQL Server

假设您使用的是Apollo Server:

// npm install @apollo/server express graphql cors 
import { ApolloServer } from '@apollo/server'; 
import { expressMiddleware } from '@apollo/server/express4'; 
import { ApolloServerPluginDrainHttpServer } from '@apollo/server/plugin/drainHttpServer'; import express from 'express'; 
import http from 'http';
import cors from 'cors';
import { typeDefs, resolvers } from './schema'; 
interface MyContext { 
   token?: String; 
 } 
 const app = express();
 const httpServer = http.createServer(app);
 const server = new ApolloServer<MyContext>({ 
     typeDefs, 
     resolvers, 
     plugins: [ApolloServerPluginDrainHttpServer({ httpServer })],
 });
 await server.start(); 
 app.use( 
     '/graphql', 
     cors<cors.CorsRequest>(), 
     express.json(),
     expressMiddleware(
         server, 
         { context: async ({ req }) => ({ token: req.headers.token }), }), 
 ); 
         
await new Promise<void>((resolve) => httpServer.listen({ port: 4000 }, resolve)); 
console.log(`🚀 Server ready at http://localhost:4000/graphql`);

在这个例子中,每个进入的请求都会执行context函数。这个函数从请求头中获取认证信息,验证用户,并将数据库连接和用户对象放入context

在解析器中使用Context

然后在解析器中,您可以访问这些context中的信息:

const resolvers = {
  Query: {
    currentUser: (_, __, context) => {
      return context.user;
    },
    getPosts: (_, __, context) => {
      return context.db.getPosts();
    }
  }
};

在这里,currentUser查询将返回当前请求中的用户信息,而getPosts查询将使用context中的数据库连接来获取帖子。

总结

context在GraphQL中作为一种将请求特定的信息(如用户身份和数据库连接)传递给解析器的机制。它增加了代码的模块化和安全性,使得每个解析器都能访问需要的共享资源和信息,而不需要创建全局变量或进行不必要的参数传递。

问题:context必须初始化时设置才能访问到吗?

在GraphQL中,context是一种向所有解析器传递信息的机制,通常是在GraphQL服务器初始化时设置的。在Apollo Server中,这是通过在ApolloServer构造函数中提供context属性来实现的。

Apollo Server中的context设置

在Apollo Server中,context是在每个请求的基础上创建的,并在请求的所有解析器之间共享。这意味着您需要在服务器初始化时定义context,这样才能在解析器中访问到它。

解析器中访问context

解析器函数的第三个参数就是context。如果您没有在Apollo Server初始化时设置context,则默认的context将是一个空对象,或者仅包含Apollo Server自动提供的基本字段。

示例中的访问

在您的示例中:

javascriptCopy code
currentUser: (_, __, context) => {
  return context.user;
},
getPosts: (_, __, context) => {
  return context.db.getPosts();
}

这里的解析器依赖于context来访问userdb对象。如果在Apollo Server初始化时没有设置这些对象,解析器将无法访问context.usercontext.db

结果

  • 设置了context:如果您在Apollo Server设置了context(如通过验证用户信息和添加数据库连接),那么解析器就能访问到这些信息。
  • 未设置context:如果未在Apollo Server中设置context,或者设置的context中不包含特定的字段(如userdb),解析器中尝试访问这些字段时将返回undefined,可能导致错误。

总结

context的正确设置对于在GraphQL解析器中访问请求特定的信息至关重要。如果您依赖于context中的某些信息,务必在Apollo Server初始化时正确设置这些信息。这是确保您的GraphQL API功能正常的关键部分。