React+GraphQL+Apollo认证:Context函数未调用致用户获取失败
我在跟着React+GraphQL+Apollo的教程实现认证功能时,遇到了一个棘手的问题:我定义的context函数完全没有被调用(日志calling context从未打印),导致Resolver里的user一直是undefined。
我的相关代码片段
Context函数:
async function context(headers, constants) { console.log('calling context') // 该日志从未打印,说明函数未被调用。 const user = await getUser(headers['authorization']) return { headers, user } }
Resolver部分:
export default { Date: GraphQLDate, Query: { currentUser: (root, args, { user }) => { console.log(user) // undefined console.log('currentUser') return hello }, // ...其他Resolver逻辑 }, // ...Mutations定义 }
可能的解决方向
我之前也碰到过类似的问题,大概率是Context函数没有被正确注册到Apollo Server里,或者版本不兼容导致的,你可以按下面的步骤排查:
检查Apollo Server的初始化配置
这是最常见的坑!你要确认在创建Apollo Server实例时,是否把这个context函数正确传递给了配置项。比如在Apollo Server v2中,正确的配置应该是这样:const server = new ApolloServer({ typeDefs, // 你的Schema定义 resolvers, // 你的Resolver对象 context: context // 这里必须明确传入你的context函数 })如果是v3及以上版本,Context函数的参数结构会不一样,它接收一个包含
req、res的对象,比如:const server = new ApolloServer({ typeDefs, resolvers, context: async ({ req }) => { console.log('calling context') const user = await getUser(req.headers.authorization) return { user } } })如果你只是写了context函数,但没在ApolloServer的配置里指定它,那这个函数永远不会被执行。
核对Context函数的参数结构
不同版本的Apollo Server对Context函数的参数要求差异很大,教程里的写法可能是针对旧版本的。如果你的Apollo Server是较新版本,还在用headers, constants作为参数,可能会因为参数不匹配导致执行异常(不过你连日志都没打,还是先确认有没有注册Context)。排查中间件或错误拦截
如果你是用Express等框架集成Apollo Server,要检查有没有中间件拦截了请求,或者错误处理逻辑吞掉了日志。可以在Apollo Server启动的地方加个简单的日志,确认服务器是否正确加载了Context配置。
你可以先重点检查Apollo Server的初始化代码,看看是不是漏传了context配置项——这几乎是这类问题的最常见原因。
内容的提问来源于stack exchange,提问作者Martin Nordström

