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

目录
相关文章
|
前端开发 Go
15 # promise 延迟对象的作用
15 # promise 延迟对象的作用
68 0
|
19天前
|
前端开发 JavaScript API
异步请求中的错误处理可以放在哪个阶段?
【10月更文挑战第29天】异步请求中的错误处理可以根据不同的错误类型和需求,放在请求发起、请求过程、请求响应以及数据处理等多个阶段进行,通过全面而细致的错误处理,可以提高应用程序的稳定性和可靠性,为用户提供更好的体验。
在路由守卫中使用箭头函数时,如何处理组件的生命周期钩子函数?
在路由守卫中使用箭头函数时,如何处理组件的生命周期钩子函数?
|
4月前
|
存储 前端开发
useEffect问题之在子组件的副作用中更新父组件的状态如何解决
useEffect问题之在子组件的副作用中更新父组件的状态如何解决
|
6月前
|
JavaScript
在Vue中,如何在组件内部使用try/catch块来处理错误?
在Vue中,如何在组件内部使用try/catch块来处理错误?
528 2
|
6月前
|
小程序
小程序封装组件简单案例,所有小程序适用(传入参数、外抛事件、传入样式)
小程序封装组件简单案例,所有小程序适用(传入参数、外抛事件、传入样式)
96 0
|
6月前
props和state相同点和不同点?render方法在哪些情况下会执行?
props和state相同点和不同点?render方法在哪些情况下会执行?
43 0
75 # koa 基本逻辑实现以及属性的扩展
75 # koa 基本逻辑实现以及属性的扩展
29 0
|
前端开发 JavaScript
【JavaScript】Promise(零) —— 准备工作(实例对象、函数对象、回调函数分类、捕获抛出错误)
【JavaScript】Promise(零) —— 准备工作(实例对象、函数对象、回调函数分类、捕获抛出错误)