<p>ошибка apollo-link-error возвращает вызывающему абоненту ошибку</p>

Созданный на 15 апр. 2019  ·  17Комментарии  ·  Источник: apollographql/apollo-link

Поэтому я использую Apollo-link-error для управления глобальными ошибками авторизации и администратора. Но если я его использую, мои методы catch в моих обещаниях не возвращают ошибок.

Похоже, что все ошибки проходят через apollo-link-error и не передаются обратно в вызывающий метод.

Есть ли способ вернуть ошибку вызывающей стороне, чтобы я мог управлять некоторыми ошибками локально и некоторыми ошибками глобально?

Самый полезный комментарий

Я нашел решение, довольно странное, но оно таково:

Это печатает только сообщение

  updateProfile: function() {
      this.$apollo
        .mutate({
          mutation: UPDATE_PROFILE,
          variables: current_user
        })
        .catch((error) => {
          console.log("this prints just the message", error);
        });
    }

НО это печатает полное содержание ошибок

  updateProfile: function() {
      this.$apollo
        .mutate({
          mutation: UPDATE_PROFILE,
          variables: current_user
        })
        .catch(({ graphQLErrors }) => {
          console.log("this prints the full content of 'errors'", graphQLErrors);
        });
    }

Думаю этот вопрос можно закрыть
@Nosherwan @romucci @Sceat @lbrdar

Все 17 Комментарий

У меня такая же проблема в моем приложении. Я хочу уловить все ошибки в ссылке на ошибку (например, чтобы я мог их зарегистрировать), но я также хочу перенаправить их исходному вызывающему абоненту и обработать их там, поскольку они могут содержать настраиваемое сообщение об ошибке, которое необходимо отобразить пользователю .

Мой код:

  • у провайдера:
const errorLink = onError(({ graphQLErrors, networkError }) => {
  if (graphQLErrors) {
    graphQLErrors.forEach(({ message, locations, path }) => {
        console.log(`[GraphQL error]: ${message}, Location: ${locations}, Path: ${path}`);
      },
    );
  }
});

const client = new ApolloClient({
  link: authLink.concat(errorLink).concat(httpLink),
  cache: new InMemoryCache(),
});

  • в компоненте:
 loginMutation({ variables: { data } })
    .then(({ data, errors }) => {
      if (errors) {
        // I WANT TO BE ABLE TO READ ERROR MESSAGE HERE SO I CAN DISPLAY IT TO THE USER
      } else if (data) {
        ....
      }
    });

Обратите внимание, что вызов forward не поможет, так как он возвращает undefined в качестве аргумента для then поэтому у меня не будет ни данных, ни ошибок, и установка errors на null тоже не вариант n, так как мне действительно нужно читать ошибки.

@lbrdar Вы нашли обходной путь для этого?

Нет

@lbrdar Разве это не способ сделать с уловом?

 loginMutation({ variables: { data } })
    .then(({ data, errors }) => {
      if (errors) {
        // I WANT TO BE ABLE TO READ ERROR MESSAGE HERE SO I CAN DISPLAY IT TO THE USER
      } else if (data) {
        ....
      }
    }).catch(errors => {

    });

@lbrdar @romucci Я столкнулся с той же проблемой. Ребята, вы разрешили это?

@Nosherwan Я только что установил версию 1.1.11, и теперь все работает нормально ... Вы также можете проверить свои внутренние обещания (возможно, где-то вы забыли вернуть обещание внутри другого обещания)

@merksam спасибо за комментарий.
Я использую ту же версию, что и вы. К сожалению, поведение такое же.

const errorLink = onError(({ graphQLErrors, networkError }) => {
  if (graphQLErrors) {
    graphQLErrors.forEach(({ message, locations, path }) => {
        console.log(`[GraphQL error]: ${message}, Location: ${locations}, Path: ${path}`);
      },
    );
  }
});

В приведенном выше блоке кода перехватываются ошибки graphQLErrors, и что-то можно сделать в обработчике onError. Однако эти ошибки не передаются в фактическое вызывающее обещание.
Я использую асинхронные функции, поэтому вместо 'then' я использую ключевое слово await, которое находится внутри блока try catch.
блок catch перехватывает ошибку, но ему не передается ошибка.

Кто-нибудь нашел обходной путь для этого?

@Nosherwan @ prem-

Я нашел решение, довольно странное, но оно таково:

Это печатает только сообщение

  updateProfile: function() {
      this.$apollo
        .mutate({
          mutation: UPDATE_PROFILE,
          variables: current_user
        })
        .catch((error) => {
          console.log("this prints just the message", error);
        });
    }

НО это печатает полное содержание ошибок

  updateProfile: function() {
      this.$apollo
        .mutate({
          mutation: UPDATE_PROFILE,
          variables: current_user
        })
        .catch(({ graphQLErrors }) => {
          console.log("this prints the full content of 'errors'", graphQLErrors);
        });
    }

Думаю этот вопрос можно закрыть
@Nosherwan @romucci @Sceat @lbrdar

как насчет добавления этого в документацию?

Извините, но решение, указанное выше, не работает. Я предполагаю, что это полный пример того, как отправить обратно graphqlErrors в link-error исходному вызывающему.

В моем случае при возникновении ошибки следующий объект ApolloQueryResult не получает сведения об ошибке, содержащиеся в onError. Некоторые в попытке ... поймать окружающий звонок. Не удается получить подробную информацию о graphqlError с сервера. Просто "ошибка 400" ..

const gqlResult: ApolloQueryResult<IGReturnData<
            IAllDataTypes
        >> = await apolloClient.query<IGReturnData<IAllDataTypes>, TVariables>({
            query: queryGql,
            variables: queryVariables,
            errorPolicy: "all",
        });

конфигурация сервера:

const errorLink = onError(({ graphQLErrors, networkError }) => {
    if (graphQLErrors)
        graphQLErrors.forEach(({ message, locations, path }) =>
            console.log(
                `[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`,
            ),
        );

    if (networkError) console.log(`[Network error]: ${networkError}`);
});

const httplink = new HttpLink({
    uri: "/graphql",
    credentials: "include",
});

const links = [errorLink, httplink];

export const apolloClient = new ApolloClient({
    link: ApolloLink.from(links),
    cache: new InMemoryCache({ addTypename: false, fragmentMatcher }),
});

@ prem-prakash спасибо .... спаситель ..

Эта проблема очень стойкая. У меня нет контроля над сервером graphql в моем проекте, только клиент. Сервер отвечает ошибками graphql в правильной форме, но с кодом состояния 400. В ссылке с ошибкой у меня есть доступ к graphQLErrors , но при мутации компонента, когда я вытаскиваю graphQLErrors как было предложено @ prem-prakash, graphQLErrors представляет собой пустой массив . Я могу получить доступ только к сообщению по умолчанию «Ошибка: сетевая ошибка: неуспешный ответ: получен код состояния 400». Apollo затирает удобочитаемые сообщения об ошибках от сервера («неверный пользователь или пароль»), потому что код состояния 400 является точкой для Apollo.

Есть ли кто-нибудь, кто может успешно обработать ответ с кодом состояния 400 с сообщениями об ошибках и передать это сообщение пользовательскому интерфейсу в компоненте, вызвавшем мутацию?

Хорошо, у меня довольно необоснованный подход, но он работает:

Я устанавливаю логическое значение hasGraphError в кеш, а также кэширую сообщение об ошибке.

const errorLink = onError(({ graphQLErrors, networkError }) => {
  if (graphQLErrors) {
    graphQLErrors.forEach(error => {
      // log gql error(s)
      console.log("[GraphQL error]: ", error);
      // cache error
      client.writeData({
        data: {
          hasGraphError: true,
          currentGraphError: error.message
        }
      });
    });
  }
  if (networkError) {
    // log network errors
    console.log("[Network error]: ", networkError);
  }
});

Затем в компоненте MutationError я запрашиваю кеш на наличие ошибки и сообщения об ошибке, условно визуализирую ошибку gql или настоящую сетевую ошибку:

const HAS_ERROR = gql`
  query IsGraphErrorPresent {
    hasGraphError <strong i="11">@client</strong>
    currentGraphError <strong i="12">@client</strong>
  }
`;
export default function MutationError({ error }) {
  const { data } = useQuery(HAS_ERROR);
  const defaultErrorMessage =
    "We're having trouble connecting. Please check your internet connection and try again.";

  // real network error
  if (error && error.message.includes("Failed to fetch")) {
    return <Error>{defaultErrorMessage}</Error>;
  }

  // graph error
  if (error && data && data.hasGraphError) {
    return <Error>{data.currentGraphError}</Error>;
  }

  // probably a real server/network error
  if (error) {
    return <Error>{defaultErrorMessage}</Error>;
  }

  return null;
}

Это будет глобально, так как он мне нужен при всех мутациях, поскольку мой сервер _ всегда_ возвращает 400 для того, что должно быть 200 + ошибок graphql (я немного соленый по этому поводу) ...

Поэтому важно то, что при каждой мутации компонента я использую пустой обратный вызов onError, который предотвращает необработанное исключение из Apollo, и в случае успеха я должен не забыть сбросить логическое значение hasGraphError в кеше:

  const [someMutation, { loading, error, client }] = useMutation(SOME_MUTATION, {
    onError() {
      // this callback prevents apollo from throwing
      // ...unhandled exception on 400 status code
    },
    onCompleted({ someMutation }) {
      client.writeData({
        data: {
          hasGraphError: false
        }
      });
    }
  });

Затем компонент ошибки мутации принимает ошибку useMutation в качестве реквизита (что позволяет определять реальные сетевые ошибки и гарантирует, что мы не отображаем глобальную кешированную ошибку gql на неправильном компоненте):

  {loading && <Spinner />}
  {error && <MutationError error={error} />}

Как я уже сказал, этот подход довольно неразумный, однако в настоящее время он работает над решением:

  1. как правило, иметь возможность обрабатывать ошибки graphql в пользовательском интерфейсе, даже если ответ имеет код состояния, отличный от 200
  2. в частности иметь возможность передавать ошибки из конфигурации apollo-link-error в вызывающий компонент для рендеринга в пользовательском интерфейсе

Проблемы с этим подходом в том виде, в каком он закодирован: он просто записывает последнюю ошибку GQL в массиве в кеш, поэтому он не поддерживает одновременную поддержку нескольких ошибок GQL. Тем не менее, это должно быть довольно легко управлять, создавая массив ошибок и сохраняя его в кеше, но вам нужно будет определить локальную схему / преобразователи для этого или, возможно, просто JSON.stringify для хранения в кеш в виде строки. Вам также нужно будет очистить currentGraphError в кеше в случае успеха, а не просто установить для логического значения false.

Надеюсь, это кому-то поможет!

Кроме того, в случае, если это помогает, обратите внимание, что errorPolicy в настоящее время не работает с хуками useMutation, это ошибка, и недавно она была рассмотрена в этом PR: https://github.com/apollographql/apollo-client/pull/5863 , но в настоящее время не выпущен.

Есть ли прогресс у разработчиков в этом вопросе?

Была ли эта страница полезной?
0 / 5 - 0 рейтинги

Смежные вопросы

SaschaDens picture SaschaDens  ·  3Комментарии

j3ddesign picture j3ddesign  ·  3Комментарии

ChenRoth picture ChenRoth  ·  4Комментарии

valerybugakov picture valerybugakov  ·  5Комментарии

NicholasLYang picture NicholasLYang  ·  4Комментарии