【发布时间】:2018-11-30 14:21:18
【问题描述】:
Apollo link offers an error handler onError
问题:
目前,我们希望在 apollo 调用期间到期时刷新 oauth 令牌,并且我们无法在 onError 中正确执行异步获取请求。
代码:
initApolloClient.js
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 }) => {
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 && clientToken) {
//let's refresh token through async request
return fromPromise(
authAPI.requestRefreshToken(refreshToken,clientToken)
.then((refreshResponse) => {
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;
})
)
}
}
}
}
}
}),
会发生什么:
- 初始 graphQL 查询运行并由于未经授权而失败
-
ApolloLink的onError函数被执行。 - 刷新令牌的承诺已执行。
-
ApolloLink的onError函数又执行了?? - 刷新令牌的承诺已完成。
- 返回初始graphQL查询结果,数据为
undefined
在第 5 步和第 6 步之间,apollo 不会重新运行初始失败的 graphQL 查询,因此结果是 undefined。
来自控制台的错误:
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
}
}
解决方案应该允许我们:
- 在操作失败时运行异步请求
- 等待请求结果
- 使用请求结果中的数据重试失败的操作
- 操作应成功返回其预期结果
【问题讨论】:
-
你能给我看看 authAPI.refreshToken() 的代码吗?
-
@MinhKha
authAPI.refreshToken()返回一个 axios 承诺,它调用身份验证端点来刷新令牌。
标签: apollo react-apollo apollo-client