Vue.js中async/await结合条件判断失效问题求助
我已经研究这个问题数小时,对async/await的工作原理愈发困惑。当前我使用Vue.js 2.1.10编写了如下代码,目标是当checkIfUniqueEmail()方法返回true时,执行console.log并触发change-stage事件,但现在变量uniqueEmail始终为undefined。请问如何修改才能在获取到checkIfUniqueEmail()的返回值为true后再执行预期逻辑?
created: function () { Event.$on('open-stage', (stage) => { this.$validator.validateAll().then(() => { const validateFields = async () => { const uniqueEmail = await this.checkIfUniqueEmail(); if(uniqueEmail) { console.log('uniqueEmail is true'); // <-- 这是我想要实现的效果 Event.$emit('change-stage', this.wizardStage.successor); } }; validateFields(); }).catch(() => { toastr.warning('Error'); Event.$emit('change-stage-denied'); return true; }); }); }, methods: { checkIfUniqueEmail() { if (!this.player.email || !this.player.email.length) { return true; } this.$http.post('playerExists', { email: this.player.email }).then(response => { if (response.data.exists) { toastr.error('Good'); Event.$emit('change-stage-denied'); return false; } return true; }).catch(error => { toastr.warning('Fail'); Event.$emit('change-stage-denied'); return false; }); }, }
问题根源
你遇到的核心问题是:checkIfUniqueEmail方法没有返回一个Promise,而await只能等待Promise对象的结果。当前你的方法里,this.$http.post是异步操作,但你只是在它的回调里返回了true/false,这些返回值并没有被作为checkIfUniqueEmail的返回值,方法本身默认返回了undefined,所以await拿到的就是undefined。
解决方案
我们需要把checkIfUniqueEmail改造成返回Promise的方法,同时调整调用逻辑确保正确等待异步结果:
1. 修改checkIfUniqueEmail方法,返回Promise
checkIfUniqueEmail() { // 如果邮箱为空,直接返回resolved状态的Promise,值为true if (!this.player.email || !this.player.email.length) { return Promise.resolve(true); } // 返回this.$http.post的Promise链,确保最终传递正确的布尔值 return this.$http.post('playerExists', { email: this.player.email }) .then(response => { if (response.data.exists) { toastr.error('Good'); Event.$emit('change-stage-denied'); return false; } return true; }) .catch(error => { toastr.warning('Fail'); Event.$emit('change-stage-denied'); return false; }); }
这里的关键是return了整个this.$http.post的Promise链,这样await就能等待这个异步操作完成,并拿到最终的true/false结果。
2. 调整validateFields的调用逻辑
因为validateFields是async函数,它本身会返回一个Promise,最好用await等待它完成,避免潜在的未处理Promise问题:
created: function () { Event.$on('open-stage', async (stage) => { // 把回调改成async函数 try { await this.$validator.validateAll(); // 这里也可以用await替代then const uniqueEmail = await this.checkIfUniqueEmail(); if(uniqueEmail) { console.log('uniqueEmail is true'); Event.$emit('change-stage', this.wizardStage.successor); } } catch () { toastr.warning('Error'); Event.$emit('change-stage-denied'); return true; } }); },
这样整个逻辑会更清晰,避免了嵌套的then回调,也符合async/await的使用习惯。
修改后的完整代码
created: function () { Event.$on('open-stage', async (stage) => { try { await this.$validator.validateAll(); const uniqueEmail = await this.checkIfUniqueEmail(); if(uniqueEmail) { console.log('uniqueEmail is true'); Event.$emit('change-stage', this.wizardStage.successor); } } catch () { toastr.warning('Error'); Event.$emit('change-stage-denied'); return true; } }); }, methods: { checkIfUniqueEmail() { if (!this.player.email || !this.player.email.length) { return Promise.resolve(true); } return this.$http.post('playerExists', { email: this.player.email }) .then(response => { if (response.data.exists) { toastr.error('Good'); Event.$emit('change-stage-denied'); return false; } return true; }) .catch(error => { toastr.warning('Fail'); Event.$emit('change-stage-denied'); return false; }); }, }
额外说明
- async函数的返回值默认会被包装成Promise,所以
await可以正确等待它的结果 - 把嵌套的then/catch改成async/await的try/catch结构,代码可读性会更高
- 确保所有异步操作都返回Promise,这样await才能发挥作用
内容的提问来源于stack exchange,提问作者Jaroslav Klimčík

