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

Nuxt 3中nuxt instance unavailable错误排查与修复求助

Nuxt3 组合式函数抛出「nuxt instance unavailable」错误解决

错误日志

Error: nuxt instance unavailable  10:42:04
    at Module.useNuxtApp (/Users/chilperic/Sites/cabinetpartage/node_modules/nuxt/dist/app/nuxt.mjs:165:13)
    at Module.useAsyncData (/Users/chilperic/Sites/cabinetpartage/node_modules/nuxt/dist/app/composables/asyncData.mjs:24:38)
    at Module.useFetch (/Users/chilperic/Sites/cabinetpartage/node_modules/nuxt/dist/app/composables/fetch.mjs:52:43)
    at Module.__vite_ssr_exports__.default (/Users/chilperic/Sites/cabinetpartage/composables/useUsers.ts:6:55)
    at Module.__vite_ssr_exports__.default (/Users/chilperic/Sites/cabinetpartage/composables/useRoomAvailability.ts:61:55)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async setup (/Users/chilperic/Sites/cabinetpartage/pages/salles/[idLocation]/[idRoom].vue:59:12)

页面调用代码

try {
    const roomAvailability = await useRoomAvailability(route.params.idRoom);
} catch (e) {
    console.log(e);
}

组合式函数代码

class RoomSchedule {
   roomId: String = "";
    days = [
        "monday",
        "tuesday",
        "wednesday",
        "thursday",
        "friday",
        "saturday",
        "sunday",
    ];
    monday = [];
    tuesday = [];
    wednesday = [];
    thursday = [];
    friday = [];
    saturday = [];
    sunday = [];

    constructor(roomId: String) {
        this.roomId = roomId;
    }

    checkAvailability(profile) {
        for (let d in this.days) {
            if (
                profile.weekly_schedule[this.days[d]] !== false &&
                profile.weekly_schedule[this.days[d]][this.roomId] !==
                    undefined &&
                profile.weekly_schedule[this.days[d]][this.roomId] == true
            ) {
                // 创建预约对象
                const apt = {
                    begins_at: "07:00",
                    ends_at: "20:00",
                    name: profile.first_name + " " + profile.last_name,
                    job: profile.job,
                    user: profile.user_id,
                };
                // 去重
                if (
                    this[this.days[d]].find(
                        (element) =>
                            JSON.stringify(element) === JSON.stringify(apt)
                    ) == undefined
                ) {
                    this[this.days[d]].push({
                        begins_at: "07:00",
                        ends_at: "20:00",
                        name: profile.first_name + " " + profile.last_name,
                        job: profile.job,
                        user: profile.user_id,
                    });
                }
            } else {
                // console.log("rien pour " + this.days[d]);
            }
        }
        return true;
    }
}

export default async (roomId: String) => {
    // 获取房间可用性
    const locationsObject = await useLocations();
    const locations = Object.values({ ...locationsObject });

    const room = locations.filter((el) => el.identifier == roomId);
    const roomAvailability = toRaw(room[0]).availability;

    let Schedule = new RoomSchedule(roomId);

    // 获取租户预约信息
    const profiles = await useUsers();

    for (let av in profiles) {
        // 遍历日期,检查租户预约
        for (let day in profiles[av].weekly_schedule) {
            await Schedule.checkAvailability(profiles[av]);
        }
    }

    return Schedule;
};

问题根源

从错误栈可定位核心问题:useUsers内部调用useFetch时无法获取Nuxt实例,本质是违反了Nuxt组合式函数调用规则:

  • useFetch/useAsyncData/useNuxtApp这类内置组合式函数,必须在setup生命周期的同步执行阶段调用,不能在异步函数的await之后、异步回调中调用,否则会丢失Nuxt实例上下文。
  • useLocations和useUsers被写成async函数,内部用await包裹useFetch,导致在useRoomAvailability中await useLocations()/await useUsers()时,实际是在异步上下文里调用useFetch,触发实例不可用错误。
  • 额外问题:checkAvailability是同步方法,无需用await调用,多余的await会加剧上下文混乱。

修复方案

步骤1:修正useLocations和useUsers的写法

不要用async/await包裹useFetch,直接返回响应式结果:

// composables/useUsers.ts
export default () => {
    // useFetch返回响应式对象,无需await
    const { data: profiles, pending, error } = useFetch('/api/users')
    return { profiles, pending, error }
}

同理修改useLocations.ts,保持一致写法。

步骤2:重构useRoomAvailability

用useAsyncData封装整个逻辑,确保所有组合式函数在同步阶段调用,同时处理响应式数据依赖:

// composables/useRoomAvailability.ts
export default (roomId: string) => {
    // 在同步阶段调用组合式函数,获取响应式数据
    const { data: locations } = useLocations()
    const { data: profiles } = useUsers()

    // 用useAsyncData处理依赖响应式数据的异步逻辑
    const { data: schedule } = useAsyncData(
        `room-schedule-${roomId}`, // 唯一key用于缓存
        async () => {
            // 等待依赖数据加载完成
            if (!locations.value || !profiles.value) return null

            const room = locations.value.find(el => el.identifier === roomId)
            if (!room) return null

            const roomSchedule = new RoomSchedule(roomId)
            // 遍历租户数据,移除多余的await
            for (const profile of profiles.value) {
                roomSchedule.checkAvailability(profile)
            }
            return roomSchedule
        },
        {
            // 当依赖项变化时自动重新执行
            watch: [roomId, locations, profiles]
        }
    )

    return schedule
}

步骤3:修正页面调用逻辑

不需要await,直接使用响应式数据:

// pages/salles/[idLocation]/[idRoom].vue
<script setup>
const route = useRoute()
const roomAvailability = useRoomAvailability(route.params.idRoom as string)

// 可选:处理加载状态
const { pending } = useRoomAvailability(route.params.idRoom as string)
</script>

额外优化建议

  • 用find替代filter[0],提升数组查找效率
  • 避免用JSON.stringify做对象比较,可改用唯一标识(比如user字段)去重,性能更优
  • 类型定义中用string替代String(小写是TS基础类型,大写是包装对象)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 23:03:08