apolloClient.query 不使用中间件,而 <Query /> 使用
apolloClient.query not using middleware, while <Query /> does
我有一个带中间件的 apolloclient,console.logs 一个不记名令牌,因为我并不总是在应该进行身份验证的时候进行身份验证。
出于某种原因,来自 react-apollo <Query />
对象的查询似乎使用了这个中间件——我看到了我的控制台消息——但是我以编程方式触发的查询:apolloClient.query
不记录任何内容(代码无法执行此操作,控制台日志位于 authLink 中间件的顶部)。
我在切换到 apolloclient 之前使用 apollo-boost 开始了我的项目,所以我认为切换后可能 node_modules 没有正确设置。但是我已经删除并重新安装了 yarn,它现在应该没有任何 apollo-boost 的痕迹了。
此外,如果我将用于创建 apolloclient
的代码复制到我的事务中,使其使用本地副本而不是全局副本,中间件就会触发。
即:
export const relayBBNToGraphcool = async () => {
/* BEGIN without this code, WHICH IS ALREADY in the instantiation of apolloClient, the result is `user: null` */
const authLink = setContext(async (req, { headers }) => {
// get the authentication token from local storage if it exists
let getToken = async () => await AsyncStorage.getItem(/*'access_token'*/'graphcool_token')
const token = await getToken()
console.trace('token for connection to graphcool is currently', token, req.operationName)
// return the headers to the context so httpLink can read them
return token
? {
headers: {
...headers,
authorization: token ? `Bearer ${token}` : null,
}
}
: { headers }
})
const httpLink = new HttpLink(config)
const link = ApolloLink.from([/* retryLink, */ authLink, httpLink])
const cache = new InMemoryCache()
// overriding apolloClient in the global scope of this module
const apolloClient = new ApolloClient({
link,
cache
})
/* END */
apolloClient.query({ query: User.self, forceFetch: true })
.then(authneticatedUser => {
console.trace('response', authneticatedUser)
if(authneticatedUser.data.user === null)
throw ('no user')
apolloClient 是从 apollo-client 而不是 apollo-boost 配置的。它在 App.js:
中附加到其提供者
return (
<ApolloProvider client={this.state.apolloClient}>
使用 getApolloClient() 从不同的文件加载——设置局部变量 apolloClient:
var apolloClient //...
export const getApolloClient = () => { // ...
apolloClient = new ApolloClient({
link,
cache
}) //...
return apolloClient
所有对 .query 或 .mutate 的调用都是从同一文件中的导出函数完成的,并且它们使用相同的 var apolloClient。我从未实例化过一个以上的 apollo-client。为什么我的一些查询触发了中间件,而其他的却没有?
编辑:
每个请求,实际使用的链接:
// from src: https://github.com/kadikraman/offline-first-mobile-example/blob/master/app/src/config/getApolloClient.js
export const getApolloClient = async () => {
const retryLink = new RetryLink({
delay: {
initial: 1000
},
attempts: {
max: 1000,
retryIf: (error, _operation) => {
if (error.message === 'Network request failed') {
//if (_operation.operationName === 'createPost')
// return true
}
return false
}
}
})
// from: https://www.apollographql.com/docs/react/recipes/authentication.html
const authLink = setContext(async (req, { headers }) => {
// get the authentication token from local storage if it exists
let getToken = async () => await AsyncStorage.getItem(/*'access_token'*/'graphcool_token')
const token = await getToken()
console.trace('token for connection to graphcool is currently', token, req.operationName)
// return the headers to the context so httpLink can read them
return token
? {
headers: {
...headers,
authorization: token ? `Bearer ${token}` : null,
}
}
: { headers }
})
const httpLink = new HttpLink(config)
const link = ApolloLink.from([retryLink, authLink, httpLink])
const cache = new InMemoryCache()
apolloClient = new ApolloClient({
link,
cache
})
try {
await persistCache({
cache,
storage: AsyncStorage
})
} catch (err) {
console.error('Error restoring Apollo cache', err) // eslint-disable-line no-console
}
return apolloClient
}
原来是缓存问题——getApolloClient方法中的这一段:
try {
await persistCache({
cache,
storage: AsyncStorage
})
} catch (err) {
console.error('Error restoring Apollo cache', err) // eslint-disable-line no-console
}
如果我更改代码以在将更改应用于发送到 ApolloProvider 的副本之前保存 apolloClient,它会起作用,如下所示:
export var apolloClient
// from src: https://github.com/kadikraman/offline-first-mobile-example/blob/master/app/src/config/getApolloClient.js
export const getApolloClient = async () => {
apolloClient = await getRawClient()
try {
await persistCache({
cache,
storage: AsyncStorage
})
} catch (err) {
console.error('Error restoring Apollo cache', err) // eslint-disable-line no-console
}
return apolloClient
}
export const getRawClient = async () => {
const retryLink = new RetryLink({
delay: {
initial: 1000
},
attempts: {
max: 1000,
retryIf: (error, _operation) => {
if (error.message === 'Network request failed') {
//if (_operation.operationName === 'createPost')
// return true
}
return false
}
}
})
// from: https://www.apollographql.com/docs/react/recipes/authentication.html
const authLink = setContext(async (req, { headers }) => {
// get the authentication token from local storage if it exists
let getToken = async () => await AsyncStorage.getItem(/*'access_token'*/'graphcool_token')
const token = await getToken()
console.trace('token for connection to graphcool is currently', token, req.operationName)
// return the headers to the context so httpLink can read them
return token
? {
headers: {
...headers,
authorization: token ? `Bearer ${token}` : null,
}
}
: { headers }
})
const httpLink = new HttpLink(config)
const link = ApolloLink.from([/* retryLink, */ authLink, httpLink])
const cache = new InMemoryCache()
return new ApolloClient({
link,
cache
})
}
然后,我还重构了这个文件中的查询和变异代码,导入了 apolloClient。 有效...这有点奇怪,但无论如何。
我有一个带中间件的 apolloclient,console.logs 一个不记名令牌,因为我并不总是在应该进行身份验证的时候进行身份验证。
出于某种原因,来自 react-apollo <Query />
对象的查询似乎使用了这个中间件——我看到了我的控制台消息——但是我以编程方式触发的查询:apolloClient.query
不记录任何内容(代码无法执行此操作,控制台日志位于 authLink 中间件的顶部)。
我在切换到 apolloclient 之前使用 apollo-boost 开始了我的项目,所以我认为切换后可能 node_modules 没有正确设置。但是我已经删除并重新安装了 yarn,它现在应该没有任何 apollo-boost 的痕迹了。
此外,如果我将用于创建 apolloclient
的代码复制到我的事务中,使其使用本地副本而不是全局副本,中间件就会触发。
即:
export const relayBBNToGraphcool = async () => {
/* BEGIN without this code, WHICH IS ALREADY in the instantiation of apolloClient, the result is `user: null` */
const authLink = setContext(async (req, { headers }) => {
// get the authentication token from local storage if it exists
let getToken = async () => await AsyncStorage.getItem(/*'access_token'*/'graphcool_token')
const token = await getToken()
console.trace('token for connection to graphcool is currently', token, req.operationName)
// return the headers to the context so httpLink can read them
return token
? {
headers: {
...headers,
authorization: token ? `Bearer ${token}` : null,
}
}
: { headers }
})
const httpLink = new HttpLink(config)
const link = ApolloLink.from([/* retryLink, */ authLink, httpLink])
const cache = new InMemoryCache()
// overriding apolloClient in the global scope of this module
const apolloClient = new ApolloClient({
link,
cache
})
/* END */
apolloClient.query({ query: User.self, forceFetch: true })
.then(authneticatedUser => {
console.trace('response', authneticatedUser)
if(authneticatedUser.data.user === null)
throw ('no user')
apolloClient 是从 apollo-client 而不是 apollo-boost 配置的。它在 App.js:
中附加到其提供者return (
<ApolloProvider client={this.state.apolloClient}>
使用 getApolloClient() 从不同的文件加载——设置局部变量 apolloClient:
var apolloClient //...
export const getApolloClient = () => { // ...
apolloClient = new ApolloClient({
link,
cache
}) //...
return apolloClient
所有对 .query 或 .mutate 的调用都是从同一文件中的导出函数完成的,并且它们使用相同的 var apolloClient。我从未实例化过一个以上的 apollo-client。为什么我的一些查询触发了中间件,而其他的却没有?
编辑:
每个请求,实际使用的链接:
// from src: https://github.com/kadikraman/offline-first-mobile-example/blob/master/app/src/config/getApolloClient.js
export const getApolloClient = async () => {
const retryLink = new RetryLink({
delay: {
initial: 1000
},
attempts: {
max: 1000,
retryIf: (error, _operation) => {
if (error.message === 'Network request failed') {
//if (_operation.operationName === 'createPost')
// return true
}
return false
}
}
})
// from: https://www.apollographql.com/docs/react/recipes/authentication.html
const authLink = setContext(async (req, { headers }) => {
// get the authentication token from local storage if it exists
let getToken = async () => await AsyncStorage.getItem(/*'access_token'*/'graphcool_token')
const token = await getToken()
console.trace('token for connection to graphcool is currently', token, req.operationName)
// return the headers to the context so httpLink can read them
return token
? {
headers: {
...headers,
authorization: token ? `Bearer ${token}` : null,
}
}
: { headers }
})
const httpLink = new HttpLink(config)
const link = ApolloLink.from([retryLink, authLink, httpLink])
const cache = new InMemoryCache()
apolloClient = new ApolloClient({
link,
cache
})
try {
await persistCache({
cache,
storage: AsyncStorage
})
} catch (err) {
console.error('Error restoring Apollo cache', err) // eslint-disable-line no-console
}
return apolloClient
}
原来是缓存问题——getApolloClient方法中的这一段:
try {
await persistCache({
cache,
storage: AsyncStorage
})
} catch (err) {
console.error('Error restoring Apollo cache', err) // eslint-disable-line no-console
}
如果我更改代码以在将更改应用于发送到 ApolloProvider 的副本之前保存 apolloClient,它会起作用,如下所示:
export var apolloClient
// from src: https://github.com/kadikraman/offline-first-mobile-example/blob/master/app/src/config/getApolloClient.js
export const getApolloClient = async () => {
apolloClient = await getRawClient()
try {
await persistCache({
cache,
storage: AsyncStorage
})
} catch (err) {
console.error('Error restoring Apollo cache', err) // eslint-disable-line no-console
}
return apolloClient
}
export const getRawClient = async () => {
const retryLink = new RetryLink({
delay: {
initial: 1000
},
attempts: {
max: 1000,
retryIf: (error, _operation) => {
if (error.message === 'Network request failed') {
//if (_operation.operationName === 'createPost')
// return true
}
return false
}
}
})
// from: https://www.apollographql.com/docs/react/recipes/authentication.html
const authLink = setContext(async (req, { headers }) => {
// get the authentication token from local storage if it exists
let getToken = async () => await AsyncStorage.getItem(/*'access_token'*/'graphcool_token')
const token = await getToken()
console.trace('token for connection to graphcool is currently', token, req.operationName)
// return the headers to the context so httpLink can read them
return token
? {
headers: {
...headers,
authorization: token ? `Bearer ${token}` : null,
}
}
: { headers }
})
const httpLink = new HttpLink(config)
const link = ApolloLink.from([/* retryLink, */ authLink, httpLink])
const cache = new InMemoryCache()
return new ApolloClient({
link,
cache
})
}
然后,我还重构了这个文件中的查询和变异代码,导入了 apolloClient。 有效...这有点奇怪,但无论如何。