Vue.js `mounted` 中是不是可以使用`async/await`?

Posted

技术标签:

【中文标题】Vue.js `mounted` 中是不是可以使用`async/await`?【英文标题】:Is `async/await` available in Vue.js `mounted`?Vue.js `mounted` 中是否可以使用`async/await`? 【发布时间】:2019-04-30 00:17:32 【问题描述】:

我想在mounted() 做这样的事情:

await fetchData1();
await fetchData2UsingData1();
doSomethingUsingData1And2();

所以我想知道这是否有效:

async mounted() 
    await fetchData1();
    await fetchData2UsingData1();
    doSomethingUsingData1And2();
,

在我的环境中,它不会引发任何错误,并且似乎运行良好。 但是在这个问题中,生命周期钩子中的async/await没有实现。

https://github.com/vuejs/vue/issues/7209

我找不到更多信息,但实际上是否可用?

【问题讨论】:

【参考方案1】:

它会起作用,因为mounted 钩子在组件已经挂载之后被调用,换句话说,它不会在渲染之前等待承诺解决。唯一的问题是,在 Promise 解决之前,您将拥有一个“空”组件。

如果您需要的是在数据准备好之前不渲染组件,那么您需要在数据中添加一个标志,与 v-if 一起使用,以便在一切准备就绪时渲染组件:

// in your template
<div v-if="dataReady">
    // your html code
</div>


// inside your script 
data () 
    return 
        dataReady: false,
        // other data
    
,

async mounted() 
    await fetchData1();
    await fetchData2UsingData1();
    doSomethingUsingData1And2();
    this.dataReady = true;
,

【讨论】:

对于其他使用 axios 来读取 api 数据的人,我可以使用上述解决方案以及 axios 的 promise 方法:async mounted () await axios.get('/api/myGetRequest').then(response =&gt; (this.mydata = response)) this.dataReady = true @Rocky await 为您解决承诺。 axios 提供了一个 async/await 示例。如果你自己处理承诺,那么 async/await 是不必要的。 @None 在我的情况下这不是真的。我的响应时间异常缓慢。也许async/await 模式允许更长的响应时间?我不确定规范,但我保证我必须履行承诺。 @None 我还应该注意,我正在通过 Vue 的 devServer.proxy 对象使用代理服务器并使用 .pathRewrite 重写路径。而且,我的要求是在加载整个页面之前等待数据。对于我最初的评论,我认为此信息超出了问题的范围,但根据您的评论,我认为可能需要注意。 我无法让asyncasync data () 上工作,所以必须使用async mounted (),如下所示。谢谢。 +1。【参考方案2】:

编辑:如文档中所述,这是一项实验性功能,目前不应在生产应用程序中使用。

在 vue3 中正确的做法是让你的 setup() 函数像这样异步:

<script>
// MyComponent.vue
export default defineComponent(
/* ... */
    async setup() 
        await fetchData1();
        await fetchData2UsingData1();
        doSomethingUsingData1And2();
        this.dataReady = true;
    

</script>

然后在父级中使用suspense component 来添加这样的后备:

<template>
    <Suspense>
        <template #default>
            <MyComponent />
        </template>
        <template #fallback>
            Loading...
        </template>
    </Suspense>
</template>

所以您会在组件加载时看到#fallback 模板,然后在组件准备好时看到组件本身。

【讨论】:

这应该有一个警告,关于悬念是实验性的,不建议用于生产。我会添加上述警告,但编辑队列目前已满。 @AlexisTyler 你说得对,我在答案的顶部添加了一个快速注释。【参考方案3】:

只需使用 $nextTick 来调用异步函数。

【讨论】:

$nextTick 是关于 DOM 渲染,async 是关于异步调用函数(简单来说:不阻塞整个应用程序)。所以,这不可能是一般意义上的解决方案。以下是of.docs 的引用:“在下一个 DOM 更新周期后延迟执行回调。在更改一些数据后立即使用它以等待 DOM 更新。”, 如果您这样做,并且感觉它可以工作,那么您可能会很难调试为什么它在以后不再工作。它(几乎)相当于制作一个await sleep(17)(休眠17ms)。如果组件的加载时间少于 17 毫秒,那就太多了。如果超过 17 毫秒,它将无法工作。而且您实际上无法预测加载需要多少时间,这取决于您的应用程序的复杂性、互联网连接、运行它的计算机的功率、月相...

以上是关于Vue.js `mounted` 中是不是可以使用`async/await`?的主要内容,如果未能解决你的问题,请参考以下文章

Vue.js请注意,mount不保证所有子组件也已安装?

vue.js 不会在mounted() 挂钩上更新

mount() 仅在组件 Vue.js 上运行一次

Vue JS:检查用户登录是不是在我的代码中不起作用

从子组件mounted()函数(Vue.js 2)列表中只收到一个发射[重复]

vue.js 中怎么使用 highCharts