记一次误用顶层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> 之所以被渲染成注释节点,看似是路由组件没有正确渲染,也有可能是组件本身出了问题。另外,在使用一些新特性要特别注意使用条件。

目录
相关文章
|
存储 JSON 数据库
vue3中实现文件上传---通过element-plus的upload组件
vue3中实现文件上传---通过element-plus的upload组件
|
缓存
vue3-ts:keepalive 列表页到详情,详情回到列表,列表恢复离开时的状态(上)
vue3-ts:keepalive 列表页到详情,详情回到列表,列表恢复离开时的状态(上)
1146 0
|
前端开发 JavaScript 安全
【前端相关】elementui使用el-upload组件实现自定义上传
【前端相关】elementui使用el-upload组件实现自定义上传
4071 0
|
10月前
|
Java Maven
apache-maven-3.9.9-src.zip 使用步骤 详细教程
下载Maven源码包并解压,确保已安装JDK 8+。进入含pom.xml的根目录,用命令`mvn clean install`编译,首次运行会自动下载依赖。成功后target目录生成可执行Maven程序,可自定义修改源码并重新构建使用。
Vue3拖拽插件(vuedraggable@next)
vuedraggable 是一款 Vue2 拖拽插件,可轻松实现列表项的拖拽排序与交互。通过简单配置,即可在不同区域间拖动元素并实现数据同步。支持多种事件监听和自定义样式。
2628 2
Vue3拖拽插件(vuedraggable@next)
|
小程序 JavaScript 前端开发
uni-app开发微信小程序:四大解决方案,轻松应对主包与vendor.js过大打包难题
uni-app开发微信小程序:四大解决方案,轻松应对主包与vendor.js过大打包难题
5341 1
|
存储 资源调度
在 Pinia 中如何实现状态持久化?
在 Pinia 中如何实现状态持久化?
3599 57
|
JavaScript 前端开发 索引
JavaScript 数组方法 slice() 的 5 个示例
slice() 方法将数组部分的副本返回到新的数组对象中。这个对象是从 start 到 end 选择的。需要注意的是,此方法不会修改原始数组。此外,如果向其中一个数组添加新元素,则另一个数组不会受到影响。
1029 0
JavaScript 数组方法 slice() 的 5 个示例