在React apollo中的每个请求之后处理错误

时间:2017-09-14 14:49:39

标签: javascript reactjs graphql-js react-apollo

如何创建能够捕获所有错误的中间件,例如我有请求哪个必需令牌,令牌可能已过期或损坏,因此我需要在每个请求中捕获此错误并能够调用查询和突变。

例如: 在过期的令牌上,我必须重新获取令牌并重复请求。 在令牌损坏时,我必须注销用户并重新获取所有查询。 我需要处理的错误类型可能很多。

In(react-apollo docs)

networkInterface.useAfter([{
  applyAfterware({ response }, next) {
    if (response.status === 401) {
      logout();
    }
    next();
  }
}]);

我无法访问graphql错误,并调用查询或突变。

1 个答案:

答案 0 :(得分:1)

您可以在发送每个请求之前检查是否有令牌。如果您没有令牌,则应该在应用程序的其他位置处理该令牌,或者可能从中间件函数直接获取另一个令牌。您可以创建更高阶的组件来包装所有必须具有令牌的组件。如果由于某种原因没有令牌,您可以获取另一个令牌并将其存储到localStorage(如果您使用的是浏览器)或asyncstorage(如果您使用的是React Native)。一旦您将其分配给localStorage或asyncStorage,下面的中间件代码片段将在您发送的每个请求之前检查令牌,这包括所有查询和突变。如果您发现您的用户没有令牌,您也可以将它们在组件中重定向到必须再次登录的页面,然后从那里将令牌设置为localstorage或asynstorage。再一次,apollo客户端的中间件将以这种方式访问​​它。

import ApolloClient, { createNetworkInterface } from 'apollo-client';
import { checkForSessionToken } from '../../utils/authentication';

const networkInterface = createNetworkInterface({
  uri: 'https://localhost:4000'
});

networkInterface.use([{
  applyMiddleware(req, next) {
    // Create the header object if needed.
    if (!req.options.headers) {
      req.options.headers = {};
    }

    // get the authentication token from Async storage
    // and assign it to the request object
    checkForSessionToken()
    .then(SESSION_TOKEN => {
      if (SESSION_TOKEN === null || SESSION_TOKEN === undefined {
          fetchNewToken()
          .then(SESSION_TOKEN => {
              localStorage.setItem('token', SESSION_TOKEN);
              req.options.headers.Authorization = `Bearer 
              ${SESSION_TOKEN}`;
          }
      } else {
       req.options.headers.Authorization = `Bearer ${SESSION_TOKEN}`;
      }

      next();
    })
    .catch(error => {
      fetchNewToken()
      .then(SESSION_TOKEN => {
          localStorage.setItem('token', token);
          req.options.headers.Authorization = `Bearer 
          ${SESSION_TOKEN}`;
      }

      next();
    })
  }
}]);

const client = new ApolloClient({
  networkInterface,
  dataIdFromObject: o => o.id
});

export default client;