如何从 apollo-link-error 获取 onError 回调中的 uri?
Posted
技术标签:
【中文标题】如何从 apollo-link-error 获取 onError 回调中的 uri?【英文标题】:How to get the uri in callback of onError from apollo-link-error? 【发布时间】:2019-12-05 08:05:44 【问题描述】:我使用 apollo-link-error 来处理 graphql 错误。我需要知道onError回调中当前链接的uri。但是,回调的签名如下:
函数(操作、响应、graphQLErrors、networkError、forward)
似乎无法从这些参数中获取 uri。所以我错过了什么吗?还是我需要使用其他工具来达到这个目的? 事实上,我需要知道 uri 用于重试目的(重试请求另一台服务器)。
我如下配置客户端,
var uriList = [uri1, uri2]
const customFetch = (uri, options) =>
const dynamicURI = getOneURIFromURIList()
return fetch(dynamicURI, options);
const errorLink = onError(( networkError, operation, forward ) =>
if (needRetry(networkError))
// Here, if I know the URI of the terminating link, I can removed it
// from the uriList, and customFetch will not choose it again.
return forward(operation)
)
const link = errorLink.concat(createHttpLink( fetch: customFetch ))
【问题讨论】:
分享您的客户端配置,包括链接,将有助于为您的问题提供更具体的答案。没有任何示例代码,很难提供一个笼统的答案。 @DanielRearden 感谢您的热情回复。我重新编辑了这个问题。在重新编辑的过程中,我发现customFetch的uri
参数可能是我想要的。当重试发生时,它是上一次调用getOneURIFromURIList
的URI吗?我还没试过。
很遗憾,经过测试,发现customFetch的uri
参数没有变化,默认是/graphql
。
使用未经测试但可行的解决方法来编辑我的答案,以解决您正在尝试做的事情。
【参考方案1】:
请求 URL 不可用作 onError
回调的参数。
客户端只包含一个terminating link——通常是HttpLink
或BatchHttpLink
。唯一的例外是当我们使用split
函数同时支持WebSocketLink
和另一个终止链接时。也就是说,您的客户通常只有一个HttpLink
,并且该链接将有一个用于发出请求的 URL——即,您通常每个客户只有一个请求 URL。除非您使用自定义链接或其他非典型设置,否则对于特定客户端,您应该已经可以在 onError
回调上下文之外访问此 URL。
编辑:
我会建议一种更传统的负载平衡方法,而不是尝试在客户端执行此操作(例如,使用实际的负载平衡器或使用 nginx 实现功能)。这样一来,您的客户端将只有一个 URL 可用于初始请求或重试,并决定将哪个服务器用于请求将由后端处理。
也就是说,您应该能够通过使用上下文和split
函数来实现您想要做的事情。像这样的东西应该可以工作:
import setContext from 'apollo-link-context'
import createHttpLink from 'apollo-link-http'
import split, from from 'apollo-link'
const contextLink = setContext(() => (
// you could return something other than the URI here, like a number
// we just need some value that's unique to each link
targetURI: getOneURIFromURIList()
))
const optionalHttpLink1 = split(
(operation) => operation.getContext().targetURI === URI_1,
createHttpLink( uri: URI_1 )
)
const optionalHttpLink2 = split(
(operation) => operation.getContext().targetURI === URI_2,
createHttpLink( uri: URI_2 )
)
const optionalHttpLink3 = split(
(operation) => operation.getContext().targetURI === URI_3,
createHttpLink( uri: URI_3 )
)
const errorLink = onError(( operation ) =>
// call operation.getContext().targetURI to determine the URI used
)
const link = from([
contextLink,
optionalHttpLink1,
optionalHttpLink2,
optionalHttpLink3,
errorLink,
])
您还需要确保删除 customFetch 选项以使上述操作生效。
还要注意split
将第二个链接作为可选的第三个参数。因此,使用两个参数,您可以指定条件和满足条件时使用的链接。使用三个参数,您可以指定一个条件、一个在满足条件时使用的链接和一个在不满足条件时使用的链接。综上所述,如果您在上面的示例中只使用两个 URI,则可以只使用一个 split
而不是三个:
const httpLink = split(
(operation) => operation.getContext().targetURI === URI_1,
createHttpLink( uri: URI_1 ),
createHttpLink( uri: URI_2 )
)
如果您有 2 个以上的 URI,则每个 URI 都需要一个 split
。
【讨论】:
非常感谢,您的回答确实帮我解决了问题。按照您的指南,我将 targetURI 放入上下文中(在您的代码中使用类似contextLink
的内容)。我仍然使用customFetch
(在我的代码中显示),在其中我可以将失败的 targetURL 从上下文中取出,然后选择一个新的来重试请求。以上是关于如何从 apollo-link-error 获取 onError 回调中的 uri?的主要内容,如果未能解决你的问题,请参考以下文章
Apollo 网络(错误请求)错误未在 apollo-link-error 中捕获