Why the behaviour of $emit with asnyc in vue2 is not same with the normal function?

28 Views Asked by At

For easy to reproduce, I use openpen to demo it.

function foo() {
    return new Promise(resolve => {
        setTimeout(resolve, 3000);
    });
}

Vue.component('child', {
    template: '<div @click="handleClick">Click</div>',
  
    methods: {
        async handleClick() {
            console.log(1);
            const a = await this.$emit('abc');
            console.log(2);
        }
    }
});

//Root Instance
new Vue({
    el: '#app',
    template: '<child @abc="handleAbc" />',
    data: {},
    methods: {
        async handleAbc() {
            console.log(3);
            await foo();
            console.log(4);
        }
    }
})

If I click the div, the result is 1 3 2 4.

function foo() {
    return new Promise((resolve) => {
        setTimeout(resolve, 3000);
    });
}

async function foo1() {
    console.log(3);
    await foo();`abc`
    console.log(4);
}

async function foo2() {
    console.log(1);
    await foo1();
    console.log(2);
}
foo2();

If I use the normal function, the result is 1 3 4 2.

Somebody can explain the reason why the result is not same.

1

There are 1 best solutions below

0
Moritz Ringler On

$emit does not return a Promise, putting an await ahead of it means to continue when all queued-up operations are handled.

Functionally, it is the same as this (numbers are in print order):

async function action(){
  console.log(1)
  await emit() // <--- run emit and put in queue
  console.log(5)
}

function emit(){
  console.log(2)
  handler() // <--- regular function call, continues when handler() returns
  console.log(4)
}

async function handler(){
  console.log(3)
  await new Promise(setTimeout) // <--- return Promise, put in queue
  console.log(6)
}

action()

Note that queued items are handled in order, so action() will continue before handler().


In your second example, the awaited function does return a Promise, execution will continue when the Promise resolves. The order becomes apparent when you replace async/await with .then() (numbers in print order):

function action(){
  console.log(1)
  return handler().then(() => {
    console.log(4)
  })
}

function handler(){
  console.log(2)
  return Promise.resolve().then(() => {
    console.log(3)
  })
}

action()