You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue2中异步$emit与普通异步函数执行行为差异原因探究

为什么Vue事件触发的异步逻辑和普通异步函数调用执行顺序不同?

场景1:Vue组件事件触发

点击组件内的div后,控制台输出顺序为:1 3 2 4

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);
        }
    }
})

场景2:普通异步函数调用

执行后控制台输出顺序为:1 3 4 2

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

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

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

核心差异原因

问题出在Vue的$emit方法的返回值上:

  • 普通异步调用场景中,await foo1()等待的是foo1这个异步函数返回的Promise,必须等foo1内部的await foo()执行完成、打印4之后,这个Promise才会resolve,所以foo2里的console.log(2)会在4之后执行。
  • Vue场景里,this.$emit('abc')只是同步触发绑定的handleAbc函数,但**$emit本身并不会返回handleAbc的Promise**,它的返回值是undefined。当你await undefined时,JavaScript会自动把它包装成一个已resolve的Promise,代码会立刻跳过等待,直接执行console.log(2)。而此时handleAbc里的await foo()还在等待3秒,等定时器结束后才会打印4,最终就出现了1 3 2 4的顺序。

内容的提问来源于stack exchange,提问作者user3300252

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 10:01:20