Поэтому я использую Apollo-link-error для управления глобальными ошибками авторизации и администратора. Но если я его использую, мои методы catch в моих обещаниях не возвращают ошибок.
Похоже, что все ошибки проходят через apollo-link-error и не передаются обратно в вызывающий метод.
Есть ли способ вернуть ошибку вызывающей стороне, чтобы я мог управлять некоторыми ошибками локально и некоторыми ошибками глобально?
У меня такая же проблема в моем приложении. Я хочу уловить все ошибки в ссылке на ошибку (например, чтобы я мог их зарегистрировать), но я также хочу перенаправить их исходному вызывающему абоненту и обработать их там, поскольку они могут содержать настраиваемое сообщение об ошибке, которое необходимо отобразить пользователю .
Мой код:
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} />}
Как я уже сказал, этот подход довольно неразумный, однако в настоящее время он работает над решением:
Проблемы с этим подходом в том виде, в каком он закодирован: он просто записывает последнюю ошибку GQL в массиве в кеш, поэтому он не поддерживает одновременную поддержку нескольких ошибок GQL. Тем не менее, это должно быть довольно легко управлять, создавая массив ошибок и сохраняя его в кеше, но вам нужно будет определить локальную схему / преобразователи для этого или, возможно, просто JSON.stringify для хранения в кеш в виде строки. Вам также нужно будет очистить currentGraphError в кеше в случае успеха, а не просто установить для логического значения false.
Надеюсь, это кому-то поможет!
Кроме того, в случае, если это помогает, обратите внимание, что errorPolicy в настоящее время не работает с хуками useMutation, это ошибка, и недавно она была рассмотрена в этом PR: https://github.com/apollographql/apollo-client/pull/5863 , но в настоящее время не выпущен.
Есть ли прогресс у разработчиков в этом вопросе?
Самый полезный комментарий
Я нашел решение, довольно странное, но оно таково:
Это печатает только сообщение
НО это печатает полное содержание ошибок
Думаю этот вопрос можно закрыть
@Nosherwan @romucci @Sceat @lbrdar