记一次误用顶层await导致的路由渲染错误

简介: 顶层 await 是ES2022的标准语法,在使用时需要注意,必须放到模块顶层使用。

背景:顶层 await

Async 异步函数能将 Promise 的链式调用的形式,改为同步的形式,对于编写和阅读代码都非常友好。但一直以来都有一个限制,就是 async 和 await 这两个关键字必须成对出现。这就导致了一个问题,想使用 await,必须要将其定义在一个 async 函数中,再调用此函数。所以 ECMAScript 中一直有一个提案,叫做顶层 await,它 支持在 async 函数以外使用 await,但是只能在一个模块的顶层中使用。这个提案于2022年正式成为 ES 标准语法。

过去的写法是这样的:

async function fn() {
  const value = await 10; // await 不仅可以接Promise,也可以将普通值
  console.log(value)
}

main();

使用顶层await 之后,就可以这样写了:

const value = await 10;
console.log(value)

但是一定有一个前提,必须处于模块的顶层。我就是没有注意这一点,导致出现了一个问题。

bug 出现

有一次开发时突发奇想,想用一下这个顶层await。于是写下了类似下面的代码:

<script setup>

const res = await axios(url)

</script>

然后过了一会,等去调试页面时才发现已经白屏了。于是打开调试工具,在元素面板中看到了整个页面的路由都没有渲染出来,只剩下一个空注释节点了:

image.png

在控制台中看到了如下警告:

[Vue warn]: Component <Anonymous>: setup function returned a promise, but no <Suspense> boundary was found in the parent component tree. A component with async setup() must be nested in a <Suspense> in order to be rendered.

起初按照直觉,以为是路由表配置出了问题,导致路由渲染不出来,反复调试路由配置,始终不奏效。然后搜索这条警告信息,果然有不少朋友都遇到过,无一例外是在 <script setup> 中使用了顶层 await。那我就纳闷了,说好的顶层await怎么不好用了呢?

盯着代码想了一会,突然想起 <script setup> 只是语法糖啊!那么上面的代码就相当于在 setup 方法中使用了 await:

<script>
export default {
  setup() {
      const res = await axios(url)
  }
}
</script>

这自然不是在模块顶层中使用了,也就导致了在解析上出现问题,导致组件不能正确渲染,最终导致对应的路由视图没有渲染出来。

小结

起初由于空页面,空节点,误解是路由的问题。其实 <router-view> 之所以被渲染成注释节点,看似是路由组件没有正确渲染,也有可能是组件本身出了问题。另外,在使用一些新特性要特别注意使用条件。

目录
相关文章
Vue3拖拽插件(vuedraggable@next)
vuedraggable 是一款 Vue2 拖拽插件,可轻松实现列表项的拖拽排序与交互。通过简单配置,即可在不同区域间拖动元素并实现数据同步。支持多种事件监听和自定义样式。
2540 2
Vue3拖拽插件(vuedraggable@next)
|
Java 数据安全/隐私保护 Spring
SpringSecurity6从入门到实战之SpringSecurity快速入门
这篇文章是关于使用SpringSecurity 6进行快速入门的教程。首先介绍了所需的环境配置,包括SpringSecurity 6.0.8、SpringBoot 3.0.12和JDK 17。接着,通过步骤展示了如何创建一个新的SpringBoot工程,并添加Web支持。然后,运行工程并测试了Hello接口,确保其正常工作。之后,引入SpringSecurity依赖后,无需额外配置,系统即实现了基础的认证功能,自动重定向到登录页面。文章通过截图详细说明了这个过程,包括控制台日志、登录页面以及登录后的资源访问。
|
JavaScript
typeScript基础(3)_ts函数默认值和可选参数
本文介绍了在TypeScript中如何使用函数的默认值和可选参数。展示了如何为函数参数指定默认值,使得在调用函数时可以省略某些参数,以及如何定义可选参数。
1153 2
|
JavaScript 前端开发 索引
JavaScript 数组方法 slice() 的 5 个示例
slice() 方法将数组部分的副本返回到新的数组对象中。这个对象是从 start 到 end 选择的。需要注意的是,此方法不会修改原始数组。此外,如果向其中一个数组添加新元素,则另一个数组不会受到影响。
979 0
JavaScript 数组方法 slice() 的 5 个示例
|
缓存
vue3-ts:keepalive 列表页到详情,详情回到列表,列表恢复离开时的状态(上)
vue3-ts:keepalive 列表页到详情,详情回到列表,列表恢复离开时的状态(上)
1090 0
|
存储 资源调度 JavaScript
Vue3如何使用Pinia详细介绍、pinia持久化存储(pinia-plugin-persistedstate详细配置)
Vue3如何使用Pinia详细介绍、pinia持久化存储(pinia-plugin-persistedstate详细配置)
|
存储 缓存 编解码
pnpm 中的 .npmrc 文件配置
.npmrc 文件是一个使用 .ini 文件格式书写的配置文件。本文介绍pnpm 中的 .npmrc 文件配置方法。
4264 0
pnpm 中的 .npmrc 文件配置
|
存储 JSON 数据库
vue3中实现文件上传---通过element-plus的upload组件
vue3中实现文件上传---通过element-plus的upload组件
|
JavaScript
Vue进阶篇(二)-彻底改变 Vue.js 状态管理:深入探讨Vue 3 Setup中的DefineModel
Vue进阶篇(二)-彻底改变 Vue.js 状态管理:深入探讨Vue 3 Setup中的DefineModel
|
JavaScript 小程序
在uniapp vue3 setup语法糖中调用onLoad、onShow等生命周期
在uniapp vue3 setup语法糖中调用onLoad、onShow等生命周期

热门文章

最新文章