Graphql 如何从apollo链接错误中获取OneError回调中的uri?

Graphql 如何从apollo链接错误中获取OneError回调中的uri?,graphql,graphql-js,Graphql,Graphql Js,我使用apollo链接错误来处理graphql错误。我需要知道onError回调中当前链接的uri。但是,回调的签名如下所示: 函数({operation,response,graphQLErrors,networkError,forward}) 似乎不可能从这些参数中获取uri。我错过了什么吗?或者我是否需要使用其他工具来实现此目的? 事实上,我需要知道uri以便重试(重试以请求另一台服务器) 我按照如下方式配置客户端: var uriList = [uri1, uri2] const cus

我使用apollo链接错误来处理graphql错误。我需要知道onError回调中当前链接的uri。但是,回调的签名如下所示:

函数({operation,response,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 }))

请求URL不能作为
onError
回调上的参数使用

客户机只包括一个单独的——通常是
HttpLink
BatchHttpLink
。唯一的例外是当我们使用
split
函数同时支持
WebSocketLink
和另一个终止链接时。所有这些都表明,您的客户端通常会有一个
HttpLink
,并且该链接将有一个用于发出请求的URL——即,通常每个客户端只有一个请求URL。除非您使用的是自定义链接或其他非典型设置,否则对于特定的客户端,您应该已经在
onError
回调的上下文之外有权访问此URL

编辑:

我建议使用一种更传统的负载平衡方法,而不是尝试在客户端进行负载平衡(例如,使用实际的负载平衡器或使用实现功能)。这样,您的客户机将只有一个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有一个
拆分

共享您的客户端配置,包括链接,将有助于为您的问题提供更具体的答案。如果没有任何示例代码,很难提供比一般答案更多的答案。@DanielRearden感谢您的友好回复。我重新编辑了这个问题。在重新编辑的过程中,我发现customFetch的
uri
参数可能就是我想要的。它是重试时对
getOneURIFromURIList
的上一次调用的URI吗?我还没有尝试过。不幸的是,在测试之后,我发现customFetch的
uri
参数没有改变,它是默认的
/graphql
。用一个未经测试但可行的解决方法编辑了我的答案,解决了您的问题。非常感谢,您的答案确实帮助我解决了问题。按照您的指导,我将targetURI放入上下文中(在代码中使用类似
contextLink
)。我仍然使用
customFetch
(显示在我的代码中),可以从上下文中获取失败的targetURL,并选择一个新的来重试请求。