成功重试时 Apollo-link @client 变异
Apollo-link @client mutation on successful retry
我在我的 React 应用程序中呈现因网络错误导致的重试通知。我希望清除任何此类通知 if/when 重新建立连接(重试成功)
我已经使用 apollo-link-retry
并使用自定义 attempts
回调在重试循环开始和超时时改变缓存。这行得通,但是当重试成功时,通知会保留在屏幕上,因为重试成功时不会调用回调,所以我无法从缓存中清除通知。
我试过使用 apollo-link-error
实现类似的逻辑并遇到类似的问题。 link 仅在发生错误且成功重试不是错误时调用。
这是我的 apollo-link-retry
配置,"almost" 有效:
const retryLink = new RetryLink({
attempts: (count) => {
let notifyType
let shouldRetry = true
if (count === 1) {
notifyType = 'CONNECTION_RETRY'
shouldRetry = true
} else if (count <= 30) {
shouldRetry = true
} else {
notifyType = 'CONNECTION_TIMEOUT'
shouldRetry = false
}
if (notifyType) {
client.mutate({
mutation: gql`
mutation m($notification: Notification!) {
raiseNotification(notification: $notification) @client
}
`,
variables: {
notification: { type: notifyType }
}
})
}
return shouldRetry
}
})
也许我需要实施自定义 link 才能完成此任务?我希望找到一种方法来利用 apollo-link-retry
的良好重试逻辑,并在逻辑进行时另外发出一些状态来缓存。
我通过做两件事实现了预期的行为:
通过 attempts
函数在 link 上下文中维护重试计数:
new RetryLink({
delay: {
initial: INITIAL_RETRY_DELAY,
max: MAX_RETRY_DELAY,
jitter: true
},
attempts: (count, operation, error) => {
if (!error.message || error.message !== 'Failed to fetch') {
// If error is not related to connection, do not retry
return false
}
operation.setContext(context => ({ ...context, retryCount: count }))
return (count <= MAX_RETRY_COUNT)
}
})
实施自定义 link 订阅错误和已完成的事件进一步向下 link 链并使用新的上下文字段来决定是否应该发出通知:
new ApolloLink((operation, forward) => {
const context = operation.getContext()
return new Observable(observer => {
let subscription, hasApplicationError
try {
subscription = forward(operation).subscribe({
next: result => {
if (result.errors) {
// Encountered application error (not network related)
hasApplicationError = true
notifications.raiseNotification(apolloClient, 'UNEXPECTED_ERROR')
}
observer.next(result)
},
error: networkError => {
// Encountered network error
if (context.retryCount === 1) {
// Started retrying
notifications.raiseNotification(apolloClient, 'CONNECTION_RETRY')
}
if (context.retryCount === MAX_RETRY_COUNT) {
// Timed out after retrying
notifications.raiseNotification(apolloClient, 'CONNECTION_TIMEOUT')
}
observer.error(networkError)
},
complete: () => {
if (!hasApplicationError) {
// Completed successfully after retrying
notifications.clearNotification(apolloClient)
}
observer.complete.bind(observer)()
},
})
} catch (e) {
observer.error(e)
}
return () => {
if (subscription) subscription.unsubscribe()
}
})
})
我在我的 React 应用程序中呈现因网络错误导致的重试通知。我希望清除任何此类通知 if/when 重新建立连接(重试成功)
我已经使用 apollo-link-retry
并使用自定义 attempts
回调在重试循环开始和超时时改变缓存。这行得通,但是当重试成功时,通知会保留在屏幕上,因为重试成功时不会调用回调,所以我无法从缓存中清除通知。
我试过使用 apollo-link-error
实现类似的逻辑并遇到类似的问题。 link 仅在发生错误且成功重试不是错误时调用。
这是我的 apollo-link-retry
配置,"almost" 有效:
const retryLink = new RetryLink({
attempts: (count) => {
let notifyType
let shouldRetry = true
if (count === 1) {
notifyType = 'CONNECTION_RETRY'
shouldRetry = true
} else if (count <= 30) {
shouldRetry = true
} else {
notifyType = 'CONNECTION_TIMEOUT'
shouldRetry = false
}
if (notifyType) {
client.mutate({
mutation: gql`
mutation m($notification: Notification!) {
raiseNotification(notification: $notification) @client
}
`,
variables: {
notification: { type: notifyType }
}
})
}
return shouldRetry
}
})
也许我需要实施自定义 link 才能完成此任务?我希望找到一种方法来利用 apollo-link-retry
的良好重试逻辑,并在逻辑进行时另外发出一些状态来缓存。
我通过做两件事实现了预期的行为:
通过 attempts
函数在 link 上下文中维护重试计数:
new RetryLink({
delay: {
initial: INITIAL_RETRY_DELAY,
max: MAX_RETRY_DELAY,
jitter: true
},
attempts: (count, operation, error) => {
if (!error.message || error.message !== 'Failed to fetch') {
// If error is not related to connection, do not retry
return false
}
operation.setContext(context => ({ ...context, retryCount: count }))
return (count <= MAX_RETRY_COUNT)
}
})
实施自定义 link 订阅错误和已完成的事件进一步向下 link 链并使用新的上下文字段来决定是否应该发出通知:
new ApolloLink((operation, forward) => {
const context = operation.getContext()
return new Observable(observer => {
let subscription, hasApplicationError
try {
subscription = forward(operation).subscribe({
next: result => {
if (result.errors) {
// Encountered application error (not network related)
hasApplicationError = true
notifications.raiseNotification(apolloClient, 'UNEXPECTED_ERROR')
}
observer.next(result)
},
error: networkError => {
// Encountered network error
if (context.retryCount === 1) {
// Started retrying
notifications.raiseNotification(apolloClient, 'CONNECTION_RETRY')
}
if (context.retryCount === MAX_RETRY_COUNT) {
// Timed out after retrying
notifications.raiseNotification(apolloClient, 'CONNECTION_TIMEOUT')
}
observer.error(networkError)
},
complete: () => {
if (!hasApplicationError) {
// Completed successfully after retrying
notifications.clearNotification(apolloClient)
}
observer.complete.bind(observer)()
},
})
} catch (e) {
observer.error(e)
}
return () => {
if (subscription) subscription.unsubscribe()
}
})
})