Почему я получаю сообщение об ошибке «Невозможно вернуть значение NULL для поля, не допускающего значения NULL» при выполнении мутации?

Я пробую свои силы в (Apollo) GraphQL на стороне сервера, и у меня возникла, вероятно, глупая проблема. Я пытаюсь зарегистрировать пользователя, но по-прежнему получаю сообщение об ошибке, показанное на изображении ниже. В чем проблема? Игнорируйте очень простой процесс аутентификации, так как я просто тестирую GraphQl

Почему я получаю сообщение об ошибке «Невозможно вернуть значение NULL для поля, не допускающего значения NULL» при выполнении мутации?

Вот соответствующие фрагменты кода:

Схема

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;
  }
},
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
24
0
43 249
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Самая большая проблема с вашим преобразователем заключается в том, что в любом количестве сценариев вместо возврата объекта User вы возвращаете строку. В вашей схеме указано, что createAccount может возвращать User или null (если бы это был User!, он не мог бы иметь значение NULL, и тогда null также не был бы допустимым типом).

Когда вы возвращаете строку в свой распознаватель, поскольку он ожидает объект, он преобразует ее в один и затем начинает искать свойства User для этого объекта (например, name и email). Эти свойства не существуют, и поскольку они являются ненулевыми свойствами в вашем объекте User, возврат для них 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"
      ]
    }
  ]
}

Если вы хотите управлять тем, как ваши ошибки отображаются на клиенте, вам следует использовать параметры конфигурации formatError или formatResponse для промежуточного программного обеспечения сервера Apollo. Также рекомендуется использовать настраиваемые ошибки, позволяя добавлять настраиваемые свойства, такие как code, для более легкого определения типа ошибки на стороне клиента.

Наконец, нет необходимости проверять, определены ли имя, адрес электронной почты или пароль внутри вашего преобразователя - в вашей схеме эти входы уже отмечены как ненулевые, что означает, что GraphQL автоматически вернет ошибку, если какой-либо из них отсутствует.

Большое спасибо за помощь. Я заставил его работать, следуя вашему совету.

Collins Orlando 25.04.2018 23:51

ПРИВЕТ, ДАНИЭЛЬ, ВЫ ГОВОРИТЕ, КАК НЕ ДОЛЖНЫ ВОЗВРАЩАТЬ строку? У меня та же проблема

PureAbap 26.12.2020 16:07

Другие вопросы по теме