Nuxt3: useFetch使用过程常见一种报错

news2025/1/16 3:32:05

一、问题描述

先看一段代码:

<script setup>
const fetchData = async () => {
  const { data, error } = await useFetch('https://api.publicapis.org/entries');
  const { data: data2, error: error2 } = await useFetch(
    'https://api.publicapis.org/entries'
  );
};

await fetchData(); // if you remove await the app will start, but server terminal will return same error
</script>

<template>
  <div>
    <NuxtWelcome />
  </div>
</template>

这段代码在不同的Nuxt版本的报错会有不同,但本质是一样的问题:

Nuxt 3.1.1:

nuxt instance unavailable

在这里插入图片描述
Nuxt 3.10.3:

[nuxt] A composable that requires access to the Nuxt instance was called outside of a plugin, Nuxt hook, Nuxt middleware, or Vue setup function. This is probably not a Nuxt bug. Find out more at `https://nuxt.com/docs/guide/concepts/auto-imports#vue-and-nuxt-composables`.

在这里插入图片描述

也可以直接访问https://stackblitz.com/edit/github-qe9ulj-opndzv?file=app.vue,在线运行代码,查看结果。

这个问题,在之前的文章《Nuxt: A composable that requires access to the Nuxt instance was called outside of a plugin…》有提到过,这次针对useFetch的使用再次遇到该问题,就再花点时间进行记录。

之所以关注到该问题,是因为对useFetch封装后,在页面setup中调用时(以某种特定的方式进行),出现了上述的错误。

为了更好的描述问题,先简单看一段能正常运行的代码:

<script setup>
const fetchData = async () => {
  const { data, error } = await useFetch('https://api.publicapis.org/entries');
};

await fetchData(); // if you remove await the app will start, but server terminal will return same error
</script>

<template>
  <div>
    <NuxtWelcome />
  </div>
</template>

这段代码与之前的相比,唯一差别就是async fetchData 内只出现了一次await useFetch的调用,但它却能正常运行:

在这里插入图片描述
一旦async fetchData 内多了一次await useFetch调用,就直接报错了:

在这里插入图片描述
但如果再换另一种方式就又正常了:

<script setup>
const fetchData = async () => {
  const res = await Promise.all([
    useFetch('https://api.publicapis.org/entries'),
    useFetch('https://api.publicapis.org/entries'),
  ]);
};

await fetchData(); // if you remove await the app will start, but server terminal will return same error
</script>

<template>
  <div>
    <NuxtWelcome />
  </div>
</template>

在这里插入图片描述
而一旦在await Promise.all之后再添加useFetch的调用就立马又报错:
在这里插入图片描述

这个问题在此看似乎可以描述为:在方法内多次调用useFetch,会导致错误
正好有一篇《Nuxt 3 useFetch - nuxt instance unavailable when using useFetch at least twice in one function》提到了这样的观点,之前的代码也是来源于此。但它的标题描述的不够准确,因为不是在方法内多次调用useFetch就一定会有问题,比如:
在这里插入图片描述
上面这样就很正常,那么出问题的地方就在于是否使用了await。为了验证这个想法,先只给第一个useFetch加上await

在这里插入图片描述
接下来,只给第二个useFetch加上await
在这里插入图片描述

至此,该问题可以描述为:在方法内一旦出现了await useFetch之后,再有useFetch的调用就会报错。

二、问题调查

前面问题描述了比较长的过程,而关于此问题也有人提到:

After calling useFetch within a function the context is lost - it should be called either directly within your setup block (in which case the context will be preserved - or you can use callWithNuxt. More info here: #14269 (comment).

在 #14269 里最后提到nuxtApp.runWithContext #23258

根据这些,可以猜测:应该是因为在useFetch在不恰当调用环境下,nuxt的context丢失,导致useFetch报错。

我们找到runWithContext的文档看看:

You are likely here because you got a “Nuxt instance unavailable” message. Please use this method sparingly, and report examples that are causing issues, so that it can ultimately be solved at the framework level.

The runWithContext method is meant to be used to call a function and give it an explicit Nuxt context. Typically, the Nuxt context is passed around implicitly and you do not need to worry about this. However, when working with complex async/await scenarios in middleware/plugins, you can run into instances where the current instance has been unset after an async call.

该runWithContext方法旨在用于调用函数并为其提供显式 Nuxt 上下文。通常,Nuxt 上下文会隐式传递,您无需担心这一点。但是,在处理中间件/插件中的复杂async/await场景时,您可能会遇到异步调用后当前实例已取消设置的情况。

A Deeper Explanation of Context
Vue.js Composition API (and Nuxt composables similarly) work by depending on an implicit context. During the lifecycle, Vue sets the temporary instance of the current component (and Nuxt temporary instance of nuxtApp) to a global variable and unsets it in same tick. When rendering on the server side, there are multiple requests from different users and nuxtApp running in a same global context. Because of this, Nuxt and Vue immediately unset this global instance to avoid leaking a shared reference between two users or components.

Vue.js Composition API(以及类似的 Nuxt 组合函数)通过依赖隐式上下文来工作。在生命周期中,Vue 将当前组件的临时实例(以及 nuxtApp 的 Nuxt 临时实例)设置为全局变量,并在同一Tick阶段销毁。在服务器端渲染时,有来自不同用户的多个请求,并且 nuxtApp 在同一全局上下文中运行。因此,Nuxt 和 Vue 立即取消设置此全局实例,以避免泄漏两个用户或组件之间的共享引用。

里面提到in same tick,这里的tick应该是跟Node Tick类似:

event loop 的每次迭代,在nodejs 中就叫做 “Tick” 。
在Node.js中,事件循环是一个持续运行的过程,负责处理事件和执行回调函数。事件循环包含了不同的阶段,其中之一就是"tick"阶段。在每个"tick"阶段,Node.js会执行以下几个主要任务:

  1. 执行微任务(microtasks):在每个"tick"阶段开始时,Node.js会首先执行所有微任务队列中的任务。微任务通常包括Promise回调、process.nextTick()等。
  2. 执行定时器检查:Node.js会检查定时器队列,查看是否有定时器到期需要执行。如果有定时器到期,Node.js会将其回调函数放入事件队列中,等待下一个"tick"阶段执行。
  3. 执行IO操作:Node.js会处理已经完成的IO操作的回调函数。这包括文件读写、网络请求等异步操作的回调函数。
  4. 执行事件回调:Node.js会执行事件队列中的事件回调函数。这些事件可能是由网络请求、定时器、IO操作等触发的。
  5. 检查是否需要继续下一个"tick"阶段:在当前"tick"阶段执行完毕后,Node.js会检查是否需要继续下一个"tick"阶段。如果事件队列中还有待处理的事件,Node.js会继续执行下一个"tick"阶段。

通过这样的"tick"阶段循环,Node.js能够高效地处理异步操作和事件回调,保证应用程序的响应性和性能。

再结合有关Vue and Nuxt composables的文档介绍:

Vue and Nuxt composables
When you are using the built-in Composition API composables provided by Vue and Nuxt, be aware that many of them rely on being called in the right context.
During a component lifecycle, Vue tracks the temporary instance of the current component (and similarly, Nuxt tracks a temporary instance of nuxtApp) via a global variable, and then unsets it in same tick. This is essential when server rendering, both to avoid cross-request state pollution (leaking a shared reference between two users) and to avoid leakage between different components.
That means that (with very few exceptions) you cannot use them outside a Nuxt plugin, Nuxt route middleware or Vue setup function. On top of that, you must use them synchronously - that is, you cannot use await before calling a composable, except within

当您使用 Vue 和 Nuxt 提供的内置 Composition API 组合函数时,请注意它们中的许多都依赖于在正确的上下文中调用。
在组件生命周期中,Vue 通过全局变量跟踪当前组件的临时实例(类似地,Nuxt 跟踪nuxtApp的临时实例),然后在同一Tick阶段销毁。这在服务器渲染时至关重要,既可以避免交叉请求状态污染(泄漏两个用户之间的共享引用),又可以避免不同组件之间的泄漏。
这意味着(除了极少数例外)你不能在 Nuxt 插件、Nuxt 路由中间件或 Vue 设置函数之外使用它们。最重要的是,您必须同步使用它们 - 也就是说,您不能在组合函数前使用await关键字,除非在<script setup>块内,在使用以defineNuxtComponent方式声明的组件的setup函数内,在defineNuxtPlugin或者defineNuxtRouteMiddleware中,这些地方即使在await后我们会执行一个转换以保持同步上下文。

也就是说,在<script setup>内,直接调用useFetch,即使useFetch前面使用await关键字也能正常访问到Nuxt Context,所以这种情况下它都能正常运行,这也是你为什么看到的useFetch的使用示例大多如此的原因:

在这里插入图片描述

通过上述介绍,现在可以知道之前描述的种种问题产生的原因,是因为在useFetch前使用await关键字,会导致它们处于不同的Tick阶段,而无法访问Nuxt Context引起报错。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1513684.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

展会邀约 | 加速科技将携重磅产品亮相SEMICON China 2024

SEMICON China 2024将于3月20日-3月22日在上海新国际博览中心隆重举行。展会期间&#xff0c;加速科技将携重磅产品高性能数模混合信号测试机ST2500EX、LCD Driver测试机Flex10K-L、高密度数模混合信号测试系统ST2500E、高性能数模混合信号测试系统ST2500A亮相此次行业盛会&…

[Java、Android面试]_02_HashMap的原理

本人今年参加了很多面试&#xff0c;也有幸拿到了一些大厂的offer&#xff0c;整理了众多面试资料&#xff0c;后续还会分享众多面试资料&#xff0c;感兴趣的朋友可收藏关注。由于时间有限&#xff0c;只能每天整理一点&#xff0c;分享一点儿&#xff01; 现分享如下&#xf…

vue3/vue2若依框架对比,点击新增编辑跳转到新页面(新增编辑共用代码)

vue2若依框架&#xff1a; router里面定义好&#xff0c;编辑里面添加一个id {path: /filmManagement,component: Layout,hidden: true,redirect: noredirect,children: [{path: editFilmDetail,component: () > import(/views/filmManagement/editFilmDetail),name: editFi…

【Mac】鼠标控制\移动\调整窗口大小BBT|边缘触发调整音量\切换桌面

一直在 win 习惯了通过鼠标的侧键来控制窗口的位置、大小&#xff0c;现在找到心的解决方案了&#xff0c;通过 BBT 设置侧键按下\抬起几颗。 以下解决方案的截图&#xff0c;其中还包括了其他操作优化方案&#xff1b; 滚轮配合 cmd 键调节页面大小&#xff1b;配合 option 键…

探索C++中的动态数组:实现自己的Vector容器

&#x1f389;个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名乐于分享在学习道路上收获的大二在校生 &#x1f648;个人主页&#x1f389;&#xff1a;GOTXX &#x1f43c;个人WeChat&#xff1a;ILXOXVJE &#x1f43c;本文由GOTXX原创&#xff0c;首发CSDN&…

算法思想总结:双指针算法

一、移动零 . - 力扣&#xff08;LeetCode&#xff09; 移动零 该题重要信息&#xff1a;1、保持非0元素的相对位置。2、原地对数组进行操作 思路&#xff1a;双指针算法 class Solution { public:void moveZeroes(vector<int>& nums){int nnums.size();for(int cur…

Elasticsearch:在本地使用 Gemma LLM 对私人数据进行问答

在本笔记本中&#xff0c;我们的目标是利用 Google 的 Gemma 模型开发 RAG 系统。 我们将使用 Elastic 的 ELSER 模型生成向量并将其存储在 Elasticsearch 中。 此外&#xff0c;我们将探索语义检索技术&#xff0c;并将最热门的搜索结果作为 Gemma 模型的上下文窗口呈现。 此外…

人工智能迷惑行为大赏!

目录 人工智能迷惑行为大赏 一&#xff1a;人工智能的“幽默”瞬间 1. 图像识别出现AI的极限 2. 小批量梯度下降优化器 3. 智能聊天机器人的冰雹问题 4. 大语言模型-3经典语录 二&#xff1a;技术原理探究 1. 深度学习 2. 机器学习 3. 自然语言处理 4. 计算机视觉 三…

java八股文 笔记(持续更新中~)

1 Redis 2Mysql 3JVM 4java基础底层 5 spring 6 微服务 7.......(持续更新) One:Redis篇 1.穿透 2&#xff1a;击穿 3&#xff1a;雪崩 3 33 4:双写一致 5.持久化 2 JVM: 2&#xff1a; 3&#xff1a; 4&#xff1a; 5&#xff1a; 6&#xff1a; 7&#xff…

学生时期学习资源同步-1 第一学期结业考试题1

原创作者&#xff1a;田超凡&#xff08;程序员田宝宝&#xff09; 版权所有&#xff0c;引用请注明原作者&#xff0c;严禁复制转载

深度学习--离线数据增强

最近做项目遇见数据集背景非常单一&#xff0c;为了增加模型的返回能里&#xff0c;只能自己做一些数据增强来增加背景的多样性。代码如下&#xff1a; import numpy as np import cv2def create_mask(box, height, width):"""创建一个全零的掩码图像&#xff…

Prompt进阶2:LangGPT(构建高性能Prompt策略和技巧)--最佳实践指南

Prompt进阶2:LangGPT(构建高性能Prompt策略和技巧)–最佳实践指南 0.前言 左图右图 prompt 基本是一样的&#xff0c;差别只在提示工程这个词是否用中英文表达。我们看到&#xff0c;一词之差&#xff0c;回答质量天壤之别。为了获得理想的模型结果&#xff0c;我们需要调整设…

uniapp开发DAPP钱包应用(二) Vue + Java

上一节我们讲了如何通过vue uniapp还有web3以及需要准备的相关组件&#xff0c;来搭建了DAPP开发的环境。 这一节&#xff0c;我们来说说如何用代码来实现DAPP相关接口。 1. ethers实现类 导入组件 import { ethers , providers , utils } from "ethers"; impor…

跟着GPT学设计模式之桥接模式

说明 桥接模式&#xff0c;也叫作桥梁模式&#xff0c;英文是 Bridge Design Pattern。在 GoF 的《设计模式》一书中&#xff0c;桥接模式是这么定义的&#xff1a;“Decouple an abstraction from its implementation so that the two can vary independently。”翻译成中文就…

我真是服了!你们刚开始学习的时候也是造火箭吗?能不能有一个简单的纯纯纯html模板给我学学,真的看不懂好嘛!

做一个个人博客第一步该怎么做&#xff1f; 好多零基础的同学们不知道怎么迈出第一步。 那么&#xff0c;就找一个现成的模板学一学呗&#xff0c;毕竟我们是高贵的Ctrl c v 工程师。 但是这样也有个问题&#xff0c;那就是&#xff0c;那些模板都&#xff0c;太&#xff01;…

弧形导轨的设计要求

制造业设备种类越来越多&#xff0c;非标自动化设备渐渐成了主力市场&#xff0c;其中弧形导轨线体作为非标自动化运输中的基石&#xff0c;承担了运输&#xff0c;定位&#xff0c;特殊工位组装&#xff0c;其设计要求也非常严格。 1、精度要求&#xff1a;弧形导轨需要具备高…

大数据 - HBase《一》- Hbase基本概念

目录 1.1. Hbase简介 1.2 Hbase,Hive, Mysql对比 1.3 Hbase数据模型 &#x1f959;region(区域) &#x1f959;rowkey(行键) &#x1f959;列族&#xff08;column family) &#x1f959;列&#xff08;column Qualifier) &#x1f959;版本&#xff08;version)-默认按…

如何仅用3行代码,搞定业务敏感数据加解密?

01 引子&#xff1a;一个数据安全的故事 一个风和日丽的早上&#xff0c;某家快递物流公司内。 &#xfeff;张老板看着电脑屏幕&#xff0c;眉头紧锁。电脑屏幕上赫然写着&#xff0c;“疑似45亿条个人信息泄露&#xff0c;电商物流行业数据安全警铃再响”。据传&#xff0c;…

代码学习记录18

随想录日记part18 t i m e &#xff1a; time&#xff1a; time&#xff1a; 2024.03.13 主要内容&#xff1a;今天的主要内容是二叉树的第七部分&#xff0c;主要涉及二叉搜索树的最近公共祖先 &#xff1b;二叉搜索树的最近公共祖先&#xff1b;删除二叉搜索树中的节点 。 23…

国内使用GPT4的5种解决方案,最后一个是全场最佳

ChatGPT4是目前世界上最先进的自然语言处理模型 大家都知道ChatGPT4特别好用 我个人来说&#xff0c;基本上每天都会用GPT来查资料、写代码和润色文章 但是在国内&#xff0c;使用ChatGPT4&#xff0c;是有一定门槛的 门槛一 mo法问题 ChatGPT的网站&#xff0c;国内是无法访问…