我正在使用apollo客户端在我的Component中进行查询。它由2个查询组成。如何在它给我401错误后阻止它向它发送另一个查询。我正在使用onError Apollo Link Error来侦听错误。然而,它会调度两个查询,我无法阻止下一个查询。
答案 0 :(得分:1)
Apollo Link Error允许您拦截和处理查询或网络错误。但是,它不提供管理后续请求的机会。为此,您需要创建自己的链接。
我过去曾经使用过类似的东西。以下示例专门处理带有刷新令牌的承载auth,但可以使用相同的原则来处理任何身份验证失败。
import { ApolloLink, Observable } from 'apollo-link';
const isAuthError = (statusCode: number) => [401, 403].includes(statusCode);
const authLink = new ApolloLink((operation, forward) => {
// Set outgoing Authorization headers
const setHeaders = () =>
operation.setContext(({ store, headers, ...rest }) => {
// get the authentication token from local storage if it exists
const token = localStorage.getItem('token');
// return the headers to the context so httpLink can read them
return {
...rest,
store,
headers: {
...headers,
authorization: `Bearer ${token}`
}
};
});
setHeaders();
return new Observable(obs => {
const subscriber = {
next: obs.next.bind(obs),
// Handle auth errors. Only network or runtime errors appear here.
error: error => {
if (isAuthError(error.statusCode)) {
// Trigger an auth refresh.
refreshTokenOrLogin()
.then(setHeaders)
.then(() => forward(operation).subscribe(subscriber));
}
}
});
} else {
obs.error(error);
}
},
complete: obs.complete.bind(obs)
};
forward(operation).subscribe(subscriber);
});
});
第一部分设置Apollo记录的身份验证上下文。您应该使用您正在使用的任何身份验证机制替换它。
operation.setContext(({ store, headers, ...rest }) => {
// get the authentication token from local storage if it exists
const token = localStorage.getItem('token');
// return the headers to the context so httpLink can read them
return {
...rest,
store,
headers: {
...headers,
authorization: `Bearer ${token}`
}
};
});
像这样的非终止链接必须返回一个observable。这允许我们像Apollo Link Error那样捕获任何网络错误,除了我们现在可以处理随后发生的事情。在这种情况下,我们创建并返回一个带有错误处理程序的新observable,它将触发auth令牌刷新,然后重试请求。下一个和完成处理程序将被传递到未触及的下一个链接。
new Observable(obs => {
const subscriber = {
next: obs.next.bind(obs),
// Handle auth errors. Only network or runtime errors appear here.
error: error => {
if (isAuthError(error.statusCode)) {
// Trigger an auth refresh.
refreshTokenOrLogin()
.then(setHeaders)
.then(() =>
// We can now retry the request following a successful token refresh.
forward(operation).subscribe(subscriber)
);
}
}
});
} else {
obs.error(error);
}
},
complete: obs.complete.bind(obs)
};
forward(operation).subscribe(subscriber);
});
将此视为2个链接可能更容易。一个设置传出的auth上下文,另一个设置捕获响应并处理auth错误。