Skip to content
开发文档
错误处理

错误处理

¥Error Handling

如果在 fetcher 内部抛出错误,钩子将返回 error

¥If an error is thrown inside fetcher, it will be returned as error by the hook.

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

如果 fetch Promise 被拒绝,则会定义 error 对象。

¥The error object will be defined if the fetch promise is rejected.

状态代码和错误对象

¥Status Code and Error Object

有时我们希望 API 在状态代码旁边返回一个错误对象。它们都对客户有用。

¥Sometimes we want an API to return an error object alongside the status code. Both of them are useful for the client.

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

¥We can customize our fetcher to return more information. If the status code is not 2xx, we consider it an error even if it can be parsed as JSON:

const fetcher = async url => {
  const res = await fetch(url)
 
  // If the status code is not in the range 200-299,
  // we still try to parse and throw it.
  if (!res.ok) {
    const error = new Error('An error occurred while fetching the data.')
    // Attach extra info to the error object.
    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 可以显示现有数据,同时知道即将到来的请求已失败。

¥Note that data and error can exist at the same time. So the UI can display the existing data, while knowing the upcoming request has failed.

此处 我们有一个例子。

¥Here we have an example.

错误重试

¥Error Retry

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

¥SWR uses the exponential backoff algorithm (opens in a new tab) to retry the request on error. The algorithm allows the app to recover from errors quickly, but not waste resources retrying too often.

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

¥You can also override this behavior via the onErrorRetry option:

useSWR('/api/user', fetcher, {
  onErrorRetry: (error, key, config, revalidate, { retryCount }) => {
    // Never retry on 404.
    if (error.status === 404) return
 
    // Never retry for a specific key.
    if (key === '/api/user') return
 
    // Only retry up to 10 times.
    if (retryCount >= 10) return
 
    // Retry after 5 seconds.
    setTimeout(() => revalidate({ retryCount }), 5000)
  }
})

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

¥This callback gives you the flexibility to retry based on various conditions. You can also disable it by setting shouldRetryOnError: false.

也可以通过 全局配置 上下文提供它。

¥It's also possible to provide it via the Global Configuration context.

全局错误报告

¥Global Error Report

你始终可以以反应方式获取组件内的 error 对象。但是,如果你想全局处理错误,通知 UI 显示 toast (opens in a new tab)snackbar (opens in a new tab),或者在 Sentry (opens in a new tab) 之类的地方报告它,则有一个 onError 事件:

¥You can always get the error object inside the component reactively. But in case you want to handle the error globally, to notify the UI to show a toast (opens in a new tab) or a snackbar (opens in a new tab), or report it somewhere such as Sentry (opens in a new tab), there's an onError event:

<SWRConfig value={{
  onError: (error, key) => {
    if (error.status !== 403 && error.status !== 404) {
      // We can send the error to Sentry,
      // or show a notification UI.
    }
  }
}}>
  <MyApp />
</SWRConfig>