You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript文件中用useRouter遇inject错误,401跳转问题如何解决

问题解决:inject() can only be used inside setup() or functional components

问题根源

你在handleFetchError函数和ofetch的onRequest回调中直接调用了useRouter()和useCookie()——这两个都是Vue/Nuxt的组合式API函数,必须在Vue组件的setup()钩子、<script setup>或者函数组件内部才能调用。当前代码在普通工具函数和ofetch配置里调用它们,脱离了Vue的响应式上下文,导致触发inject()错误(useRouter内部依赖inject获取路由实例)。

最佳解决方案

把$api的创建逻辑移到Nuxt插件中,利用插件的上下文环境安全调用组合式API,再将$api注册为全局可用实例:

步骤1:创建Nuxt插件文件

在项目plugins目录下新建api.ts(或api.client.ts仅客户端运行):

import { ofetch } from 'ofetch'
import type { Plugin } from '#app'

export class CustomFetchError extends Error {
  public code: number
  public response?: Response
  constructor(code: number, message: string, response?: Response) {
    super(message)
    this.code = code
    this.name = 'CustomFetchError'
    this.response = response
  }
}

export default defineNuxtPlugin((nuxtApp) => {
  const router = useRouter()
  const HttpStatusCodesWasHandled = [401] // 替换为你实际需要处理的状态码数组

  const handleFetchError = (response: Response) => {
    if (HttpStatusCodesWasHandled.includes(response.status)) {
      if (response.status === 401) {
        router.push('/auth')
      }
      throw new CustomFetchError(response.status, 'Error Was Handled', response)
    } else {
      throw new CustomFetchError(0, 'Error Not Handled', response)
    }
  }

  const $api = ofetch.create({
    baseURL: import.meta.env.VITE_API_BASE_URL || '/api',
    timeout: 10000,
    async onRequest({ options }) {
      const accessToken = useCookie('accessToken').value
      if (accessToken) {
        options.headers = {
          ...options.headers,
          Authorization: `Bearer ${accessToken}`,
        }
      }
    },
    async onResponse({ response }) {
      if (!response.ok) {
        handleFetchError(response)
      }
    },
    async onResponseError({ response }) {
      if (!response.ok) {
        handleFetchError(response)
      }
    },
  })

  // 将$api注入全局,组件内可直接调用
  nuxtApp.provide('api', $api)
})

步骤2:组件/页面中使用$api

在Vue组件或页面中通过useNuxtApp获取实例:

const { $api } = useNuxtApp()

// 示例请求
try {
  const userData = await $api('/user/profile')
} catch (err) {
  // 自定义错误处理
}

替代方案(非插件方式)

如果不想用Nuxt插件,可在客户端环境用原生方式处理,但无法兼容服务端渲染:

// 修改handleFetchError的路由跳转逻辑
if (response.status === 401) {
  if (process.client) {
    window.location.href = '/auth'
  }
}

// 修改onRequest的cookie读取逻辑
async onRequest({ options }) {
  let accessToken = ''
  if (process.client) {
    accessToken = document.cookie.split('; ').find(row => row.startsWith('accessToken='))?.split('=')[1] || ''
  }
  if (accessToken) {
    options.headers = {
      ...options.headers,
      Authorization: `Bearer ${accessToken}`,
    }
  }
},

优先推荐Nuxt插件方案,它能更好融入Nuxt生态,支持服务端渲染和上下文管理。

内容的提问来源于stack exchange,提问作者mohsen ahmadi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 03:27:31