Is `async/await` available in Vue.js `mounted`?
Asked Answered
R

4

85

I'd like to do something like this in mounted() {}:

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

So I wonder if this works:

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

In my environment it raises no errors, and seems to work well. But in this issue, async/await in lifecycle hooks is not implemented.

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

I could not find further information, but is it available in fact?

Remscheid answered 28/11, 2018 at 6:38 Comment(0)
F
132

It will work because the mounted hook gets called after the component was already mounted, in other words it won't wait for the promises to solve before rendering. The only thing is that you will have an "empty" component until the promises solve.

If what you need is the component to not be rendered until data is ready, you'll need a flag in your data that works along with a v-if to render the component when everything is ready:

// 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;
},
Foppish answered 28/11, 2018 at 6:56 Comment(5)
For anyone else working with axios to read api data, I was able to use the above solution along with axios's promises methodology: async mounted () { await axios.get('/api/myGetRequest').then(response => (this.mydata = response)) this.dataReady = true }Abbey
@Rocky await resolves the promise for you. axios provides an async/await example. If you handle the promise yourself then async/await is unnecessary.Roundshouldered
@Roundshouldered This was not true in my case. I was working with an exceptionally slow response time. Perhaps the async/await pattern allows for longer response times? I am not sure of the spec, but I promise that I had to handle the promise.Abbey
@Roundshouldered I should note, too, that I was working with a proxy server via Vue's devServer.proxy object and rewriting the path using .pathRewrite. And, my requirement was to wait on the data before loading the entire page. For my original comment, I thought this info to be beyond the scope of the question, but per your comment, I thought it might be relevant to note.Abbey
I couldn't get async working on async data () so had to use async mounted () as shown here. Thanks. +1.Fallon
R
9

Edit: As stated in the documentation, this is an experimental feature and should not be used in production applications for now.

The correct way to do this in vue3 would be to make your setup() function async like this:

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

And then use a suspense component in the parent to add a fallback like this:

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

So you would see the #fallback template while the component is loading, and then the component itself when it's ready.

Rn answered 12/8, 2021 at 19:59 Comment(0)
F
1

Given that I came here wondering how to implement this when using the new CompositionApi in Vue, this is how it works with defining it inside onMounted():

<script setup lang="ts">
  async function doSomething(): Promise<number> {
    return Promise.resolve(0);
  }

  onMounted(async () => {
    const result = await doSomething();
  });
</script>
Fishy answered 1/2 at 11:21 Comment(0)
T
-18

Just use $nextTick to call async functions.

Towle answered 25/11, 2019 at 22:36 Comment(2)
$nextTick is about DOM rendering, and async is about calling functions asynchronously (in simple words: non-blocking the whole application). So, it couldn't be a solution in the general sense. Here is a quote from the of.docs: "Defer the callback to be executed after the next DOM update cycle. Use it immediately after you’ve changed some data to wait for the DOM update.",Elgar
If you do this, and it feels like it work, you'll probably have a very bad time debugging why it won't work anymore down the road. It's (almost) equivalent to make a await sleep(17) (to sleep 17ms). It will be too much if the component take less than 17ms to load. It won't work if it takes more than 17ms. And you can't actually predict how much time it will take to load, it depends on the complexity of your app, the internet connection, the power of the computer running it, the phase of the moon...Rn

© 2022 - 2024 — McMap. All rights reserved.