Apollo客户端异步刷新令牌

时间:2020-05-11 17:51:47

标签: reactjs graphql apollo react-apollo apollo-client

当发生未经身份验证的错误时,我一直在努力异步刷新Apollo客户端中的令牌。 我已经审查了一些资源,例如StackOverflow答案,this Github问题和this博客文章。

最主要的是在获得新令牌后,等待重试失败的请求。阅读上面博客中的评论和Github问题中的评论,似乎很多人都成功地解决了这个问题,但是,重试完成后,我获得了带有新令牌的数据,这意味着重试是仍然使用旧令牌完成,因此失败。

这是执行刷新突变的函数。


export const getNewToken = (client) => {
  const refreshToken = getRefreshToken();
  return client.mutate({
    mutation: REFRESH_TOKEN,
    variables: { refreshToken },
  });
};

这是Auth链接,我对令牌进行了console.log来知道使用了哪个令牌。

const authLink = setContext((_, { headers }) => {
  // get the authentication token from local storage if it exists
  const token = localStorage.getItem("token");
  console.log("Token in auth link: ", token);
  return {
    headers: {
      ...headers,
      authorization: token ? `JWT ${token}` : "",
    },
  };
});

然后在Apollo的onError函数中,我试图在上面链接的博客中重新创建第三个示例:

if (token && refreshToken) {
  return fromPromise(
    getNewToken(client)
      .then(({ data: { refreshToken } }) => {
        console.log("Promise data: ", refreshToken);
        localStorage.setItem("token", refreshToken.token);
        localStorage.setItem("refreshToken", refreshToken.refreshToken);
        return refreshToken.token;
      })
      .catch((error) => {
        // Handle token refresh errors e.g clear stored tokens, redirect to login, ...
        console.log("Error after setting token: ", error);
        return;
      })
  )
    .filter((value) => {
      console.log("In filter: ", value);
      return Boolean(value);
    })
    .flatMap(() => {
      console.log("In flat map");
      // retry the request, returning the new observable
      return forward(operation);
    });
}

执行此操作存在两个问题: 1.根本没有调用filterflatMap函数。 2. authLink用旧令牌记录了呼叫之后,便收到了新令牌。这意味着forward(operation)不会等待新令牌。

我还尝试了链接博客的并发请求。那里还有更多事情要做,所以这里是整个src/index.js的全部内容 https://gist.github.com/bzhr/531e1c25a4960fcd06ec06d8b21f143b

这里forward$.flatMap并没有被称为AT ALL。还有与上面的示例相同的问题。

我不确定我的错误在哪里,因为许多人在博客上评论了该博客对他们有用。我已多次检查代码。我需要一些调试方面的帮助。最主要的是要等待重试,直到新令牌准备就绪。

1 个答案:

答案 0 :(得分:0)

我也是这个面临的问题,但终于使它奏效了。

  1. 代替fromPromise。我使用了一个util方法,该方法使用Observables来订阅我们的Promise .then方法。
const _promiseToObservable = promiseFunc =>
  new Observable(subscriber => {
    promiseFunc.then(
      value => {
        if (subscriber.closed) return;
        subscriber.next(value);
        subscriber.complete();
      },
      err => subscriber.error(err),
    );
    return subscriber; // this line can removed, as per next comment
  });

之后,在OnError中,使用此util方法而不是fromPromise调用getNewToken()方法。

  1. 如果要用于GraphQlErrors,请删除for循环。以第一个数组元素graphQlErrors [0]为例,该数组元素通常包含我们的错误数据。

进行这两个更改对我有用。