Nuxt3中$fetch未按预期捕获HTTP 401响应,如何获取状态码?
Nuxt3中$fetch捕获HTTP 401状态码的疑问
我在开发Nuxt3项目时,试图捕获HTTP 401状态码来刷新访问令牌,在@/utils/useApi.js中写了以下代码:
try { let apiData = await $fetch(url, fetchOpts) .then((res) => { if (res.status == '200') { return res } else { // 我原本预期HTTP 401响应会进入这里 } }).catch(async e => { // 但实际进入了这里,起初不知道如何获取HTTP状态 }) return apiData } catch (e) { console.error('api error: ', e) }
我原本预期401响应会进入.then()分支,但实际进入了catch(),这是为什么?我哪里写错了?或者如何在catch中获取HTTP状态?
补充:控制台看不到e的有效数据,但可以通过e.status获取HTTP状态码。
为什么401会进入catch分支?
Nuxt3的$fetch基于ofetch实现,默认会把所有HTTP状态码≥400的响应都视为错误,自动触发catch分支,而非进入then。这是ofetch的设计逻辑:仅状态码在2xx范围内的响应会被判定为成功,走then处理;4xx/5xx这类错误状态码会直接抛出异常,进入catch。你之前的逻辑错误地认为非200的状态码仍会走then,但401属于4xx客户端错误,符合触发catch的条件。
如何在catch中处理401?
你通过e.status获取状态码的方式是正确的。另外,ofetch的错误对象还包含e.response属性,可获取完整的响应内容(如响应体、headers等)。调整后的代码示例:
try { let apiData = await $fetch(url, fetchOpts) .then((res) => { // 仅处理2xx状态码的响应 return res }).catch(async e => { // 统一处理4xx/5xx错误 if (e.status === 401) { // 在此编写刷新访问令牌的逻辑 // 例如调用刷新接口、更新本地token后重试请求 console.log('触发令牌刷新逻辑') } else { // 处理其他错误场景 console.error('请求错误:', e.status, e.response?._data) } // 根据业务需求决定是否抛出错误或返回默认值 throw e }) return apiData } catch (e) { console.error('api error: ', e.status || e.message) }
额外选项:让所有响应进入then分支
如果希望非200的状态码也进入then处理,可以在fetchOpts中配置ignoreResponseError: true,之后自行判断状态码:
let apiData = await $fetch(url, { ...fetchOpts, ignoreResponseError: true }) .then((res) => { if (res.status === 200) { return res } else if (res.status === 401) { // 处理401逻辑 } else { // 处理其他状态码 } })
不过这种方式需要手动处理所有状态码,不如默认的catch分支逻辑清晰,推荐优先使用默认逻辑在catch中处理401。
内容的提问来源于stack exchange,提问作者cony
相关产品推荐
相关产品推荐

