0

我有 2 个关于 GraphQL 的问题。

  1. 我使用创建了一个架构,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
    })
}))

executableSchema但我想知道这是否是同时传递schema和的正确方法rootValue

  1. 我该如何实现该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的 as,union以便我可以在前端收到更具体的错误消息,以处理不同的错误消息。

这就是我LoginResultschema样子

    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
          }
        }

任何帮助都会得到帮助!

4

1 回答 1

1

rootValue是传递给您的查询和变异解析器的值(作为父值)。该值很少使用,但您可以使用它将任何内容传递给这些解析器。

您的类型名称和返回的字符串__typename需要完全相同。例如,您的类型似乎被调用PasswordError,但您返回类型名称PasswordIncorrect

于 2020-07-17T15:14:16.297 回答