当前位置: 首页 > news >正文

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

一、问题描述

先看一段代码:

<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引起报错。

相关文章:

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

一、问题描述 先看一段代码&#xff1a; <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);…...

当代计算机语言占比分析

在当今快速发展的科技领域&#xff0c;计算机语言作为程序员的工具之一&#xff0c;扮演着至关重要的角色。随着技术的不断演进&#xff0c;各种编程语言层出不穷&#xff0c;但在实际开发中&#xff0c;哪些计算机语言占据主导地位&#xff1f;本文将对当代计算机语言的占比进…...

基于大模型和向量数据库的 RAG 示例

1 RAG 介绍 RAG是一种先进的自然语言处理方法&#xff0c;它结合了信息检索和文本生成技术&#xff0c;用于提高问答系统、聊天机器人等应用的性能。 2 RAG 的工作流程 文档加载&#xff08;Document Loading&#xff09; 从各种来源加载大量文档数据。这些文档…...

【C语言】比较两个字符串大小,strcmp函数

目录 一&#xff0c;strcmp函数 1&#xff0c;strcmp函数 2&#xff0c;函数头文件&#xff1a; 3&#xff0c;函数原型&#xff1a; 4&#xff0c;返回取值&#xff1a; 二&#xff0c;代码实现 三&#xff0c;小结 一&#xff0c;strcmp函数 1&#xff0c;strcmp函数 …...

深入理解与应用Keepalive机制

目录 引言 一、VRRP协议 &#xff08;一&#xff09;VRRP概述 1.诞生背景 2.基本理论 &#xff08;二&#xff09;VRRP工作原理 &#xff08;三&#xff09;VRRP相关术语 二、keepalive基本理论 &#xff08;一&#xff09;基本性能 &#xff08;二&#xff09;实现原…...

嵌入(embedding)概念

嵌入&#xff08;embedding&#xff09;在数学和相关领域中的确是指将一个数学对象在保持其某些关键性质不变的前提下&#xff0c;注入到一个更大或更高维的空间中。这个过程不仅仅是简单的映射&#xff0c;而是要求注入的对象在新空间中的表现形式能够完整反映原有对象的内在结…...

豆瓣书影音存入Notion

使用Python将图书和影视数据存放入Notion中。 &#x1f5bc;️介绍 环境 Python 3.10 &#xff08;建议 3.11 及以上&#xff09;Pycharm / Vs Code / Vs Code Studio 项目结构 │ .env │ main.py - 主函数、执行程序 │ new_book.txt - 上一次更新书籍 │ new_video.…...

Lucene 分词 示例代码

import org.apache.lucene.analysis.tokenattributes.CharTermAttribute; import org.apache.lucene.analysis.TokenStream; import org...

2.18 校招 实习 内推 面经

绿*泡*泡VX&#xff1a; neituijunsir 交流*裙 &#xff0c;内推/实习/校招汇总表格 1、自动驾驶一周资讯 - 李想回应“年终奖有点大”&#xff1b;智界升级为奇瑞独立事业部&#xff1b;小鹏汽车春节累计智驾总里程公布 自动驾驶一周资讯 - 李想回应“年终奖有点大”&…...

spring中事务失效的场景有哪些?

异常捕获处理 在方法中已经将异常捕获处理掉并没有抛出。 事务只有捕捉到了抛出的异常才可以进行处理&#xff0c;如果有异常业务中直接捕获处理掉没有抛出&#xff0c;事务是无法感知到的。 解决&#xff1a;在catch块throw抛出异常。 抛出检查异常 spring默认只会回滚非检…...

Visual Studio 2022之Release版本程序发送到其它计算机运行

目录 1、缺少dll​ 2、应用程序无法正常启动 3、This application failed to start because no Qt platform plugin could be initialized. 代码在Debug模式下正常运行&#xff0c;然后切换到Release模式下&#xff0c;也正常运行&#xff0c;把第三方平台的dll拷贝到exe所在…...

Xcode下载模拟器报错Could not download iOS 17.4 Simulator (21E213).

xcode14以后最小化安装包&#xff0c;从而将模拟器不集中在安装包中 因此xcode14至以后的版本安装后第一次启动会加载提示安装模拟器的提示框 或者根据需要到xcode中进行所需版本|平台的模拟器进行安装 Xcode > Settings > Platforms 问题来了尝试多次都安装失败例如…...

mac在终端设置代理

前言 本篇文章介绍如何在mac终端设置代理服务器&#xff0c;有时候&#xff0c;我们需要在终端进行外网的资源访问&#xff0c;比如我构建v8引擎项目的时候&#xff0c;需要使用gclient更新组件和下载构建工具。如果单单设置了计算机的代理&#xff0c;依然是无法下载资源的&a…...

傅立叶之美:深入研究傅里叶分析背后的原理和数学

一、说明 T傅里叶级数及其伴随的推导是数学在现实世界中最迷人的应用之一。我一直主张通过理解数学来理解我们周围的世界。从使用线性代数设计神经网络&#xff0c;从混沌理论理解太阳系&#xff0c;到弦理论理解宇宙的基本组成部分&#xff0c;数学无处不在。 当然&#xff0c…...

golang学习随便记16-反射

为什么需要反射 下面的例子中编写一个 Sprint 函数&#xff0c;只有1个参数&#xff08;类型不定&#xff09;&#xff0c;返回和 fmt.Fprintf 类似的格式化后的字符串。实现方法大致为&#xff1a;如果参数类型本身实现了 String() 方法&#xff0c;那调用 String() 方法即可…...

识别恶意IP地址的有效方法

在互联网的环境中&#xff0c;恶意IP地址可能会对网络安全造成严重威胁&#xff0c;例如发起网络攻击、传播恶意软件等。因此&#xff0c;识别恶意IP地址是保护网络安全的重要一环。IP数据云将探讨一些有效的方法来识别恶意IP地址。 IP地址查询&#xff1a;https://www.ipdata…...

探索信号处理:低通滤波器的原理与应用

在信号处理领域&#xff0c;滤波器的应用至关重要&#xff0c;它能够帮助我们从复杂的信号中提取需要的信息&#xff0c;而低通滤波器则是其中一种被广泛应用的滤波器类型。本文旨在深入探讨低通滤波器的基本原理、主要类型以及在实际应用中的作用和实现方式。 ### 1. 低通滤波…...

计算机网络:应用层知识点汇总

文章目录 一、网络应用模型二、域名系统&#xff08;DNS&#xff09;三、文本传输协议&#xff08;FTP&#xff09;四、电子邮件五、万维网和HTTP协议 一、网络应用模型 p2p也就是对等模型 二、域名系统&#xff08;DNS&#xff09; 我们知道&#xff0c;随着人们建立一个网站…...

金三银四!一个年薪160W+的就业方向!

前言 随着越来越多的科技大厂加入鸿蒙生态建设&#xff0c;鸿蒙开发人才正在市场上被争抢。资深工程师开出的年薪高达近百万&#xff0c;架构师更是高至160万&#xff0c;真可谓“鸿蒙猿年薪超百万”。如何抓住新技术红利&#xff0c;尽早上车&#xff1f;你会成为下一个鸿蒙开…...

实现的一个网页版的简易表白墙

实现的一个网页版的表白墙 实现效果 代码截图 相关代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><tit…...

后进先出(LIFO)详解

LIFO 是 Last In, First Out 的缩写&#xff0c;中文译为后进先出。这是一种数据结构的工作原则&#xff0c;类似于一摞盘子或一叠书本&#xff1a; 最后放进去的元素最先出来 -想象往筒状容器里放盘子&#xff1a; &#xff08;1&#xff09;你放进的最后一个盘子&#xff08…...

(十)学生端搭建

本次旨在将之前的已完成的部分功能进行拼装到学生端&#xff0c;同时完善学生端的构建。本次工作主要包括&#xff1a; 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

DAY 47

三、通道注意力 3.1 通道注意力的定义 # 新增&#xff1a;通道注意力模块&#xff08;SE模块&#xff09; class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

linux arm系统烧录

1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 &#xff08;忘了有没有这步了 估计有&#xff09; 刷机程序 和 镜像 就不提供了。要刷的时…...

Keil 中设置 STM32 Flash 和 RAM 地址详解

文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

ETLCloud可能遇到的问题有哪些?常见坑位解析

数据集成平台ETLCloud&#xff0c;主要用于支持数据的抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;和加载&#xff08;Load&#xff09;过程。提供了一个简洁直观的界面&#xff0c;以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

【python异步多线程】异步多线程爬虫代码示例

claude生成的python多线程、异步代码示例&#xff0c;模拟20个网页的爬取&#xff0c;每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程&#xff1a;允许程序同时执行多个任务&#xff0c;提高IO密集型任务&#xff08;如网络请求&#xff09;的效率…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码

目录 一、&#x1f468;‍&#x1f393;网站题目 二、✍️网站描述 三、&#x1f4da;网站介绍 四、&#x1f310;网站效果 五、&#x1fa93; 代码实现 &#x1f9f1;HTML 六、&#x1f947; 如何让学习不再盲目 七、&#x1f381;更多干货 一、&#x1f468;‍&#x1f…...

使用Spring AI和MCP协议构建图片搜索服务

目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式&#xff08;本地调用&#xff09; SSE模式&#xff08;远程调用&#xff09; 4. 注册工具提…...