Poniższy wpis dotyczy własnej obsługi błędów sieciowych w aplikacjach opartych o stack Vue / React + Apollo (Graphql).
Dodanie własnej obsługi błędów może być pomocne, jeśli w przypadku wystąpienia zdarzenia, chcemy podjąć jakąś akcję np: wysłanie alertu, dodanie wpisu w logach czy zakomunikowanie użytkownikowi o niepowodzeniu wykonywanego żądania.
Apollo umożliwia co najmniej 2 sposoby na własną obsługę błędów.
Pierwszy na poziomie query jest przypisany konkretnemu rodzajowi zapytania.
Do naszego komponentu, w którym używamy apollo
, należy dodać hook error
, który jest wywoływany w przypadku niepowodzenia. Parametr err
to obiekt Apollo error zawierający dwa kolejne obiekty: graphQLErrors
oraz networkError
.
apollo: {
myQuery: {
query: gql`query test {
id
name
}`,
result ({ data, loading, networkStatus }) {
console.log('We got some result!')
},
// Error handling
error (err) {
console.error('We\'ve got an error!', err)
},
}
}
Drugim sposobem jest dodanie globalnego handlera. W tym przypadku należy skorzystać z klasy apollo-link
, która jest wymagana do utworzenia instancji ApolloClient.
apollo-link
jest podzielone na Linki, które można łączyć w zależności od potrzeb. Dla klasycznych rozwiązań z użyciem protokoły HTTP polecane jest użycie apollo-link-http
.
Podłączenie Apollo do aplikacji Vue wygląda następująco:
import { ApolloClient } from 'apollo-client';
import { HttpLink } from 'apollo-link-http';
import { InMemoryCache } from 'apollo-cache-inmemory';
const httpLinkApi = new HttpLink({
// You should use an absolute URL here
uri: `${location.origin}/v1/graph`,
});
// Cache implementation
const cache = new InMemoryCache();
// Create the apollo client
const apolloClient = new ApolloClient({
link: httpLinkApi,
cache,
connectToDevTools: true,
});
const apolloProvider = new VueApollo({
defaultClient: apolloClient,
});
new Vue({
el: '#app',
apolloProvider,
render: (h) => h(App),
});
Przejdźmy do obsługi błędów.
Nasz kod musi zostać rozszerzony o kolejny Link, a dokładniej apollo-link-error
.
Rozbudujmy kod o następujące fragment:
import { ApolloLink } from 'apollo-link';
import { onError } from 'apollo-link-error';
// …
const linkErr = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors)
graphQLErrors.forEach(({ message, locations, path }) =>
console.log(
`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`
)
);
});
const apolloClient = new ApolloClient({
link: ApolloLink.from([linkErr, httpLinkPerlApi]),
cache,
connectToDevTools: true,
});
Jak widać kolejne rodzaje Linków można łączyć, aby stworzyć dokładnie to co potrzebujemy, lecz należy pamiętać o użyciu ApolloLink.from()
.
PS: Chcąc wyciągnąć informacje o statusie odpowiedzi HTTP, możemy użyć poniższego rozwiązania:
if (networkError && 'statusCode' in networkError) {
if (networkError.statusCode >= 300 && networkError.statusCode < 400) {
window.location.reload();
}
}
Więcej informacji i typów linków można znaleźć w oficjalnej dokumentacji https://www.apollographql.com/docs/link/ .