Skip to content
文档
错误处理

错误处理

如果在 fetcher 中抛出错误,hook 会将其作为 error 返回。

const fetcher = url => fetch(url).then(r => r.json())
 
// ...
const { data, error } = useSWR('/api/user', fetcher)

如果 fetch promise 被拒绝,将定义 error 对象。

状态码和错误对象

有时我们希望 API 在返回状态码的同时返回一个错误对象。它们对客户端都是有用的。

我们可以自定义 fetcher 以返回更多信息。如果状态码不是 2xx,我们则认为它是一个错误,即使它可以被解析为 JSON:

const fetcher = async url => {
  const res = await fetch(url)
 
  // 如果状态码不在 200-299 的范围内,
  // 我们仍然尝试解析并抛出它。
  if (!res.ok) {
    const error = new Error('An error occurred while fetching the data.')
    // 将额外的信息附加到错误对象上。
    error.info = await res.json()
    error.status = res.status
    throw error
  }
 
  return res.json()
}
 
// ...
const { data, error } = useSWR('/api/user', fetcher)
// error.info === {
//   message: "You are not authorized to access this resource.",
//   documentation_url: "..."
// }
// error.status === 403
💡

注意:dataerror 可以同时存在。所以 UI 可以在知道即将到来的请求失败时显示现有数据。

这里有一个示例。

错误重试

在出现错误时 SWR 使用指数退避算法 (opens in a new tab)重发请求。该算法允许应用从错误中快速恢复,而不会浪费资源频繁地重试。

你还可以通过 onErrorRetry 选项覆盖该行为:

useSWR('/api/user', fetcher, {
  onErrorRetry: (error, key, config, revalidate, { retryCount }) => {
    // 404 时不重试。
    if (error.status === 404) return
 
    // 特定的 key 时不重试。
    if (key === '/api/user') return
 
    // 最多重试 10 次。
    if (retryCount >= 10) return
 
    // 5秒后重试。
    setTimeout(() => revalidate({ retryCount: retryCount }), 5000)
  }
})

这个回调让你可以灵活的根据各种条件重试。你也可以通过设置 shouldRetryOnError: false 来禁用它。

也可以通过全局配置 context 来提供它。

全局错误报告

你总是可以响应性的在组件内部得到 error 对象。但如果你想要全局处理错误,通知 UI 显示一个 toast (opens in a new tab) 或者一个 snackbar (opens in a new tab),或在某处报告它,比如 Sentry (opens in a new tab),可以用 onError 事件:

<SWRConfig value={{
  onError: (error, key) => {
    if (error.status !== 403 && error.status !== 404) {
      // 我们可以把错误发送给 Sentry,
      // 或显示一个通知 UI。
    }
  }
}}>
  <MyApp />
</SWRConfig>