Skip to content

Navigation Menu

Sign in
Sign up

Apollo и REST

Leonid Fenko edited this page Jul 15, 2019 · 3 revisions

REST должен использоваться только в случае крайней необходимости (например, требование заказчика). При этом обязательно надо рассмотреть возможность написания GraphQL-прослойки над REST.

Обработка ошибок

Необходимо конвертировать известные ошибки сети в GraphQL-ошибки. Умышленно или нет, Apollo обрабатывает их по-разному:

  • Ошибка сети прерывает getDataFromTree() даже при fetchPolicy: 'all'
  • Ошибка сети в <Query> родительского компонента приводит к игнорированию <Query> дочернего компонента (при SSR)

Пример конвертации ошибок

/** Number code, string code, like: [400, 'InvalidAuthDataError'] */
type NetworkError = [number, string];
interface ProcessableError {
 statusCode?: number;
 result: { code?: string; message?: string };
}
/** Converts given network errors to GraphQL errors */
function getErrorConverterLink(networkErrorList: NetworkError[]) {
 return new ApolloLink((operation, forward) => {
 return new Observable<FetchResult>(observer => {
 let sub: ZenObservable.Subscription;
 try {
 sub = forward!(operation).subscribe({
 next(result) {
 observer.next(result);
 },
 error(networkError) {
 if (isNetworkErrorKnown(networkError, networkErrorList)) {
 const processableError = networkError as ProcessableError;
 observer.next({
 errors: [
 new GraphQLError(
 processableError.result.message || 'Unknown network error',
 undefined,
 undefined,
 undefined,
 undefined,
 networkError,
 { code: processableError.result.code },
 ),
 ],
 });
 }
 observer.error(networkError);
 },
 complete: observer.complete.bind(observer),
 });
 } catch (e) {
 observer.error(e);
 }
 return () => {
 if (sub) sub.unsubscribe();
 };
 });
 });
}
function isNetworkErrorKnown(networkError: Error | null, networkErrorList: NetworkError[]) {
 return (
 !networkError ||
 (isProcessableError(networkError) &&
 networkErrorList.find(ignoreError => {
 const processableError = (networkError as unknown) as ProcessableError;
 return (
 ignoreError[0] === processableError.statusCode && ignoreError[1] === processableError.result.code
 );
 }))
 );
}
function isProcessableError<T>(error: T | null): error is T & ProcessableError {
 return Boolean(error && (error as any).result);
}

Clone this wiki locally

AltStyle によって変換されたページ (->オリジナル) /