title: How to execute an async fetch request and then retry last failed request?
body: <p><a href="https://github.com/apollographql/apollo-link/tree/master/packages/apollo-link-error#retrying-failed-requests" rel="noreferrer">Apollo link offers an error handler <code>onError</code></a></p>
  
  <p><strong>Issue:</strong>
  Currently, we wish to refresh oauth tokens when they expires during an apollo call and we are unable to execute an async fetch request inside the <code>onError</code> properly. </p>
  
  <p><strong>Code:</strong></p>
  
  <p><code>initApolloClient.js</code>
  </p>
  
  <pre><code>import { ApolloClient } from 'apollo-client';
  import { onError } from 'apollo-link-error';
  import { ApolloLink, fromPromise } from 'apollo-link';
  
  //Define Http link
  const httpLink = new createHttpLink({
      uri: '/my-graphql-endpoint',
      credentials: 'include'
  });
  
  //Add on error handler for apollo link
  
  return new ApolloClient({
      link: ApolloLink.from([
          onError(({ graphQLErrors, networkError, operation, forward  }) =&gt; {
              if (graphQLErrors) {
                  //User access token has expired
                  if(graphQLErrors[0].message==="Unauthorized") {
                      //We assume we have both tokens needed to run the async request
                      if(refreshToken &amp;&amp; clientToken) {
                          //let's refresh token through async request
                          return fromPromise(
                              authAPI.requestRefreshToken(refreshToken,clientToken)
                              .then((refreshResponse) =&gt; {
                                  let headers = {
                                      //readd old headers
                                      ...operation.getContext().headers,
                                      //switch out old access token for new one
                                      authorization: `Bearer ${refreshResponse.access_token}`,
                                  };
  
                                  operation.setContext({
                                      headers
                                  });
  
                                  //Retry last failed request
                                  return forward(operation);
                              })
                              .catch(function (error) {
                                  //No refresh or client token available, we force user to login
                                  return error;
                              })
                          )
                      }
                  }
              }
          }
      }
  }),
  </code></pre>
  
  <p>What happens is:</p>
  
  <ol>
  <li>Initial graphQL query runs and fails due to unauthorization</li>
  <li>The <code>onError</code> function of <code>ApolloLink</code> is executed.</li>
  <li>The promise to refresh the token is executed.</li>
  <li>The <code>onError</code> function of <code>ApolloLink</code> is executed again??</li>
  <li>The promise to refresh the token is completed.</li>
  <li>The initial graphQL query result is returned and its data is <code>undefined</code></li>
  </ol>
  
  <p>Between step 5 and 6, <em>apollo doesn't re-run the initial failed graphQL query</em> and hence the result is <code>undefined</code>.</p>
  
  <p><strong>Errors from console:</strong></p>
  
  <pre class="lang-js prettyprint-override"><code>Uncaught (in promise) Error: Network error: Error writing result to store for query:
   query UserProfile($id: ID!) {
    UserProfile(id: $id) {
      id
      email
      first_name
      last_name
      }
      __typename
    }
  }
  </code></pre>
  
  <p>The solution should allow us to:</p>
  
  <ol>
  <li>Run an async request when an operation fails</li>
  <li>Wait for the result of the request</li>
  <li>Retry failed operation with data from the request's result</li>
  <li>Operation should succeed to return its intended result</li>
  </ol>