image
https://unsplash.com/photos/2zGTh-S5moM

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.

Lokalny

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)
        },
    }
}

Globalny

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/ .