如何执行异步提取请求,然后重试上一个失败的请求? [英] How to execute an async fetch request and then retry last failed request?
本文介绍了如何执行异步提取请求,然后重试上一个失败的请求?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
问题:
目前,我们希望在opol令牌在阿波罗调用期间到期时刷新它们,并且我们无法在onError
内部正确执行异步获取请求.
Issue:
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 onError
properly.
代码:
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
- Initial graphQL query runs and fails due to unauthorization
- The
onError
function ofApolloLink
is executed. - The promise to refresh the token is executed.
- The
onError
function ofApolloLink
is executed again?? - The promise to refresh the token is completed.
- The initial graphQL query result is returned and its data is
undefined
在第5步和第6步之间, apollo不会重新运行最初失败的graphQL查询,因此结果为undefined
.
Between step 5 and 6, apollo doesn't re-run the initial failed graphQL query and hence the result is 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
}
}
该解决方案应允许我们:
The solution should allow us to:
- 操作失败时运行异步请求
- 等待请求的结果
- 使用请求结果中的数据重试失败的操作
- 操作应成功返回其预期结果
推荐答案
我正在以这种方式刷新令牌(更新的OP):
I'm refreshing the token this way (updated OP's):
import { ApolloClient } from 'apollo-client';
import { onError } from 'apollo-link-error';
import { ApolloLink, Observable } from 'apollo-link'; // add Observable
// 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 }) => {
// User access token has expired
if (graphQLErrors && 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 new Observable(observer => {
authAPI.requestRefreshToken(refreshToken, clientToken)
.then(refreshResponse => {
operation.setContext(({ headers = {} }) => ({
headers: {
// Re-add old headers
...headers,
// Switch out old access token for new one
authorization: `Bearer ${refreshResponse.access_token}` || null,
}
}));
})
.then(() => {
const subscriber = {
next: observer.next.bind(observer),
error: observer.error.bind(observer),
complete: observer.complete.bind(observer)
};
// Retry last failed request
forward(operation).subscribe(subscriber);
})
.catch(error => {
// No refresh or client token available, we force user to login
observer.error(error);
});
});
}
}
})
])
});
这篇关于如何执行异步提取请求,然后重试上一个失败的请求?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文