如何在express中实现resolveType函数/初始化graphQL服务器
Posted
技术标签:
【中文标题】如何在express中实现resolveType函数/初始化graphQL服务器【英文标题】:how to implement resolveType function / initialise graphQL server in express 【发布时间】:2020-11-07 09:15:08 【问题描述】:我有 2 个关于 GraphQL 的问题。
-
我使用
makeExecutableSchema
创建了一个模式,所以我可以创建一个executableSchema
。
我像这样导出executableSchema
并在我的app.js
中初始化服务器。
app.use('/graphql', graphqlHTTP(
schema: executableSchema,
rootValue: executableSchema,
graphiql: true,
customFormatErrorFn: (error) => (
message: error.message,
locations: error.locations,
stack: error.stack ? error.stack.split('\n') : [],
path: error.path
)
))
但我想知道为schema
和rootValue
传递executableSchema
是否是正确的方法?
-
如何实现
resolveType
函数以及在哪里实现?
我收到一条错误消息
Error: Abstract type "LoginResult" must resolve to an Object type at runtime for field "Query.login" with value __typename: "EmailNotFound" , received "undefined". Either the "LoginResult" type should provide a "resolveType" function or each possible type should provide an "isTypeOf" function.
一般来说,我将LoginResult
创建为union
,这样我就可以在前端收到更具体的错误消息,以处理不同的错误消息。
这就是我在schema
中的LoginResult
的样子
type AuthData
token: String!
refreshToken: String!
userId: String!
type EmailError
message: String
type PasswordError
message: String
type VerificationError
message: String
union LoginResult = AuthData | EmailError | PasswordError | VerificationError
type Query
login(email: String!, password: String!): LoginResult!
和login
解析器方法看起来像这样
const resolvers =
Query:
login: async function ( email, password )
try
const user = await User.findOne( email: email )
const errors = []
if(!user)
const error = new Error('User not found.')
error.code = 404
errors.push('404')
return
__typename: 'EmailNotFound'
// throw error
const isEqual = await bcrypt.compare(password, user.password)
if(!isEqual)
const error = new Error('Password is incorrect.')
error.code = 401
errors.push('401')
// throw error
return
__typename: 'PasswordIncorrect'
if(!user.isVerified)
const error = new Error('Please verify your email address')
error.code = 403
errors.push('403')
// throw error
return
__typename: 'NotVerified'
// if (errors.length > 0)
// const error = new Error('Invalid input.')
// error.data = errors
// error.code = 422
// throw error
//
const token = jwt.sign(
userId: user._id.toString(),
email: user.email
,
JWT_SECRET_KEY,
expiresIn: '30min'
)
const refreshToken = jwt.sign(
userId: user._id.toString(),
email: user.email
,
JWT_SECRET_KEY,
expiresIn: '1h'
)
return
token,
refreshToken,
userId: user._id.toString(),
__typename: 'AuthData'
catch(err)
console.log(err)
这就是我从前端创建查询的方式
const graphqlQuery =
query: `
query UserLogin($email: String!, $password: String!)
login(email: $email, password: $password)
__typename
...on AuthData
token
userId
...on EmailError
message
...on PasswordError
message
...on VerificationError
message
`,
variables:
email,
password
如有任何帮助,我们将不胜感激!
【问题讨论】:
您是如何创建架构的?使用buildSchema
?
@DanielRearden 我正在使用'const makeExecutableSchema = require('@graphql-tools/schema').makeExecutableSchema' 它基于我阅读的这个***,我发现'makeExecutableSchema'->@987654321 @
【参考方案1】:
rootValue
是传递给您的查询和变异解析器的值(作为父值)。此值很少使用,但您可以使用它将任何内容传递给这些解析器。
您的类型名称和您在__typename
中返回的字符串必须完全相同。例如。您的类型似乎被称为PasswordError
,但您返回类型名称PasswordIncorrect
。
【讨论】:
我完全按照您的建议更改了它们,现在它显示不同的错误,显示“无法解构'未定义'的属性'电子邮件',因为它是未定义的”。想知道是什么导致了这个未定义? 是的,解析器的第一个参数是父值而不是参数。更改解析器的签名:login: async function (parent, email, password , context)
非常感谢,它有效!另一个问题。 “父”值是否也是所有其他解析器方法中的第一个参数?它是“graphql-tools”语法吗?
通常是第一个参数。这是由reference implementation 引入的,并已被许多框架和语言采用。如果您能接受并支持我的回答,那将对我有很大帮助:)
是的,它始终是第一个值。 __typename
只需要由解析为联合类型或接口类型的解析器返回。以上是关于如何在express中实现resolveType函数/初始化graphQL服务器的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 nodejs 和 express 在 REST API 中实现搜索和过滤
如何使用express-validator在单独的文件中实现验证
如何在 node express 中实现 JWT(JsonWebToken) 注销
如何在 React/Express 应用程序中实现可选身份验证?