message: clean up fetch and remove abort controller
  Abort controller was being called after every fetch. This caused subsequent queries to be aborted
diff: -import { Observable } from 'rxjs';
  import { flatMap } from 'rxjs/operators';
  import { Exchange } from '../types';
  -import { CombinedError } from '../lib/error';
  +import { CombinedError } from '../lib';
  -export const fetchExchange: Exchange = () => ops$ =>
  +export const fetchExchange: Exchange = () => {
  + return ops$ =>
  ops$.pipe(
  - flatMap(operation => {
  - const { url, fetchOptions } = operation.context;
  - const { operationName } = operation;
  -
  - if (operationName === 'subscription') {
  + flatMap(async operation => {
  + if (operation.operationName === 'subscription') {
  throw new Error(
  'Received a subscription operation in the httpExchange. You are probably trying to create a subscription. Have you added a subscriptionExchange?'
  );
  @@ -19,79 +16,55 @@ export const fetchExchange: Exchange = () => ops$ =>
  query: operation.query,
  variables: operation.variables,
  });
  - // https://developer.mozilla.org/en-US/docs/Web/API/AbortController/AbortController
  - const abortController = createAbortController();
  - return new Observable(observer => {
  - let response;
  + let response: Response;
  + let result: any;
  - fetch(url, {
  + try {
  + const { url, fetchOptions } = operation.context;
  + response = await fetch(url, {
  body,
  headers: { 'Content-Type': 'application/json' },
  method: 'POST',
  - signal: abortController.signal,
  ...fetchOptions,
  - })
  - .then(res => (response = res))
  - .then(checkStatus(fetchOptions.redirect))
  - .then(res => res.json())
  - .then(result => {
  - let error;
  - if (Array.isArray(result.errors)) {
  - error = new CombinedError({
  - graphQLErrors: result.errors,
  - response,
  });
  - }
  - observer.next({
  + checkStatus(fetchOptions.redirect, response);
  +
  + result = await response.json();
  +
  + return {
  operation,
  data: result.data,
  - error,
  - });
  + error: Array.isArray(result.errors)
  + ? new CombinedError({
  + graphQLErrors: result.errors,
  + response,
  })
  - .catch(err => {
  + : undefined,
  + };
  + } catch (err) {
  if (err.name === 'AbortError') {
  return;
  }
  - const error = new CombinedError({
  - networkError: err,
  - response,
  - });
  -
  - observer.next({
  + return {
  operation,
  data: undefined,
  - error,
  - });
  - });
  -
  - return () => {
  - if (abortController.abort) {
  - abortController.abort();
  - }
  + error: new CombinedError({
  + networkError: err,
  + response,
  + }),
  };
  - });
  + }
  })
  );
  -
  -const createAbortController = () => {
  - if (typeof AbortController === 'undefined') {
  - return { abort: null, signal: undefined };
  - }
  -
  - return new AbortController();
  };
  -const checkStatus = (redirectMode: string = 'follow') => (
  - response: Response
  -) => {
  - // If using manual redirect mode, don't error on redirect!
  +const checkStatus = (redirectMode: string = 'follow', response: Response) => {
  const statusRangeEnd = redirectMode === 'manual' ? 400 : 300;
  - if (response.status >= 200 && response.status < statusRangeEnd) {
  - return response;
  - }
  + if (response.status < 200 || response.status > statusRangeEnd) {
  throw new Error(response.statusText);
  + }
  };
  