错误处理
¥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
注意,data
和 error
可以同时存在。因此,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>