【问题标题】:Why am I getting a "Cannot return null for non-nullable field" error when doing a mutation? [duplicate]为什么在执行突变时会出现“无法为不可为空的字段返回 null”错误? [复制]
【发布时间】:2018-10-05 21:28:40
【问题描述】:

我正在尝试在服务器端使用 (Apollo) GraphQL,并且遇到了一个可能很愚蠢的问题。我正在尝试注册用户,但不断收到下面链接图片中显示的错误。问题是什么?忽略非常简单的身份验证流程,因为我只是在测试 GraphQl

这里是相关代码sn-ps:

架构

export default `

type User {
    id: ID!
    name: String!
    email: String!
}

type Query {
    allUsers: [User]
  currentUser: User
}

type Mutation {
    createAccount(name: String!, email: String!, password: String!): User
    loginUser(email: String!, password: String!): User
    updatePassword(email: String!, password: String!, newPassword: String!): User
    deleteAccount(email: String!, password: String!): User
}

`

解析器

createAccount: async (
  parent,
  { name, email, password },
  { User },
  info
) => {
  try {
    // Check for invalid (undefined) credentials
    if (!name || !email || !password) {
      return 'Please provide valid credentials';
    }

    // Check if there is a user with the same email
    const foundUser = await User.findOne({ email });

    if (foundUser) {
      return 'Email is already in use';
    }

    // If no user with email create a new user
    const hashedPassword = await bcrypt.hash(password, 10);
    await User.insert({ name, email, password: hashedPassword });

    const savedUser = await User.findOne({ email });

    return savedUser;
  } catch (error) {
    return error.message;
  }
},

【问题讨论】:

    标签: javascript node.js express graphql apollo-server


    【解决方案1】:

    解析器的最大问题是,在任何情况下,您都不会返回User 对象,而是返回一个字符串。您的架构指定createAccount 可以返回Usernull(如果它是User!,则它不能为空,然后null 也不是有效类型)。

    当您在解析器中返回一个字符串时,因为它需要一个对象,它会将其强制为一个,然后开始在该对象上查找User 属性(如nameemail)。这些属性不存在,并且因为它们是 User 对象上的非 null 属性,因此为它们返回 null/undefined 会导致错误。

    您的解析器可能应该只抛出它需要抛出的任何错误。然后它们将作为errors 数组的一部分在您的响应中返回。例如:

    // Check if there is a user with the same email
    const foundUser = await User.findOne({ email })
    
    if (foundUser) throw new Error('Email is already in use')
    
    // If no user with email create a new user
    const hashedPassword = await bcrypt.hash(password, 10);
    await User.insert({ name, email, password: hashedPassword });
    
    const savedUser = await User.findOne({ email });
    
    return savedUser;
    

    现在,如果您有重复的电子邮件,回复将如下所示:

    {
      "data": {
        "createAccount": null
      },
      "errors": [
        {
          "message": "Email is already in use",
          "locations": [
            {
              "line": 4,
              "column": 3
            }
          ],
          "path": [
            "createAccount"
          ]
        }
      ]
    }
    

    如果您想控制错误在客户端上的显示方式,您应该为您的 Apollo 服务器中间件使用 formatErrorformatResponse 配置选项。使用自定义错误也是一种很好的做法,允许您添加自定义属性,如 code,以便更轻松地识别客户端的错误类型。

    最后,没有必要检查您的解析器中是否定义了名称、电子邮件或密码——您的架构已经将这些输入标记为非空,这意味着如果其中任何一个缺失,GraphQL 将自动返回错误。

    【讨论】:

    • 非常感谢您的帮助。听从你的建议,我得到了它的工作。
    • 嗨,丹尼尔你是说硬件不应该返回字符串吗?我也面临同样的问题
    • 我的美分,就我而言,我忘记在 DataSource API 回调中使用 return 语句。这篇文章有助于了解该领域的原因!谢谢。
    猜你喜欢
    • 2021-02-16
    • 1970-01-01
    • 2021-03-18
    • 2021-05-21
    • 2021-10-07
    • 2021-11-27
    • 2021-10-24
    • 2023-03-28
    • 1970-01-01
    相关资源
    最近更新 更多