【踩坑】空return无法保存、当if语句通过的情况下,else逻辑中的异步请求仍会被执行,如何处理异步请求后面的同步代码?

问题描述

做添加购物车功能的时候,要求点击弹层中的"加入购物车"按钮时,
若未登录就先弹出二次确认框,
若已登录则调用添加购物车的封装api接口
代码如下:

// 点击弹层中的按钮:"加入购物车"
handleAddCart () {
  if (!this.userInfo.token) { // token不存在:弹出提示框
    // Dialog确认框
    this.$dialog.confirm({
      title: '温馨提示',
      message: '此时需要先登录才能继续操作哦',
      confirmButtomText: '去登录',
      cancelButtonText: '再逛逛'
    }).then(() => {
      this.$router.replace({
        path: '/login',
        query: {
          backUrl: this.$route.fullPath
        }
      })
    }).catch(() => {
      // 点击了取消按钮
      this.showPannel = false
    })
  } else {//token存在:已登录
    addCart(this.goodsId, this.addCount, this.goodsSkuId).then((res) => {
      this.cartTotal = res.data.cartTotal
      this.msg = res.message
      console.log('获取添加购物车的cartTotal:', this.cartTotal)
      this.$toast(this.msg)
    })
    this.addCartMethods()
    this.$toast(this.msg)
    this.showPannel = false
  }
},

此处出现问题,即,在未登录状态下点击"加入购物车",二次确认框弹出之前,控制台会报错如下:

index.js??
clonedRuleSet-40.use[0]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!
./src/views/ProductDetail/index.vue?vue&type=script&lang=js:156 
Uncaught (in promise)
解决方法:在if的最后添加return,确保代码不会往下执行

此时写入一个空的return并保存,vscode的插件(如 ESLint、Prettier 或 VSCode 的代码格式化工具)会自动删除 return 行
解决方法是

  • .eslintrc.js 中禁用 no-useless-return 规则
module.exports = {
  rules: {
    'no-useless-return': 'off' // 允许显式 return
  }
};
  • 显式添加注释
if (!this.userInfo.token) {
  this.showLoginDialog();
  // eslint-disable-next-line no-useless-return
  return; // 必须显式终止,避免后续代码执行
}
为什么return不能省略?

即使 token 不存在,代码仍会继续执行 else 块中的逻辑(addCart() 和 this.$ toast(this.msg)),导致:

  • 发送无效的 addCart 请求(可能因未登录返回 401 错误)。

  • 显示空的 this.$ toast(this.msg)(因为 this.msg 未被赋值)。

  • 弹层被意外关闭(this.showPannel = false 被执行)。

为什么if条件已经成立的情况下仍然会执行else中调用异步接口的操作?

if-else 的分支选择是同步的,但 addCart() 是一个异步操作(Promise)
而 this.$ toast() 和 this.showPannel = false 是同步代码,
它们会在 addCart() 发起请求后立即执行,无论 if 条件是否成立。

期望中的业务流程为:

  • 如果 token 不存在,执行 if 分支,显示弹窗并 return,后续代码不会执行
  • 如果 token 存在,跳过 if 分支,直接执行 else 中的所有代码(包括 addCart() 和后续的同步代码)。

但实际上的业务流程为:
addCart() 返回一个 Promise,但 .then() 中的回调是异步的,不会阻塞后续同步代码。
因此,this.$ toast(this.msg) 和 this.showPannel = false 会在 addCart() 请求 刚发起时就立即执行,此时:

  • this.msg 还未被赋值
  • 弹层会被同步代码关闭
优化添加购物车的业务逻辑如下

方案一:将同步代码移入 .then()

if (!this.userInfo.token) {
  // 未登录逻辑
  this.$ dialog.confirm({ /* ... */ });
  return;
}
// 已登录逻辑(无需 else,直接写后续代码)
addCart(this.goodsId, this.addCount, this.goodsSkuId)
  .then((res) => {
    this.cartTotal = res.data.cartTotal;
    this.msg = res.message;
    this.$ toast(this.msg); // 在异步回调中执行
    this.addCartMethods();
    this.showPannel = false; // 请求完成后关闭弹层
  });

方案二:使用 async/await

async handleAddCart() {
  if (!this.userInfo.token) {
    await this.$ dialog.confirm({ /* ... */ });
    return;
  }
  try {
    const res = await addCart(this.goodsId, this.addCount, this.goodsSkuId);
    this.cartTotal = res.data.cartTotal;
    this.msg = res.message;
    this.$ toast(this.msg);
    this.addCartMethods();
  } finally {
    this.showPannel = false; // 确保无论成功失败都关闭弹层
  }
}

总结:
避免在异步操作后直接写同步代码(除非你明确需要它们立即执行)。
使用 async/await 可以让异步逻辑更接近同步代码的阅读体验

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端OnTheRun

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值