Vue 项目中主从表异步保存实战:缓存导致接口不执行问题排查与解决

发布于:2025-08-13 ⋅ 阅读:(13) ⋅ 点赞:(0)

一、项目背景

在开发企业级管理系统时,常见的业务场景是多张主从表数据联合保存。比如一个“资金利息付款”功能,涉及:

  • 主表:资金利息付款信息(如付款批次、总金额等)

  • 从表1:付款明细列表(interestPaymentList)

  • 从表2:付款退回明细列表(interestRefundList)

前端业务逻辑通常是:

  1. 先调用主表保存接口,返回主表 ID。

  2. 主表保存成功后,附加主表 ID 给从表数据。

  3. 并行调用两个从表保存接口。

  4. 最终统一处理保存成功/失败的结果。

二、核心代码示例

下面是本项目中保存主从表的核心函数 submiteParams

submiteParams(params) {
  if (this.action.type == 'update' && !this.action.isCopy) {
    params.entity.interestPaymentId = this.action.id
    params.entity.batchId = this.action.batchId
  }
  
  if (this.action.relativeData && Object.keys(this.action.relativeData).length) {
    params = { ...params, ...this.action.relativeData }
  }
  
  pmInterestPaymentSaveAPI(params).then(res => {
    this.loading = false
    
    const interestPaymentId = res.data.interestPayment // 主表ID
    const documentCode = res.data.documentCode || ''
    
    // 给付款从表加主表ID、单据编号
    const paymentInfoList = this.interestPaymentList.map(item => ({
      ...item,
      interestPaymentId,
      documentCode
    }))
    
    // 给付款退回从表加主表ID、单据编号
    const refundInfoList = this.interestRefundList.map(item => ({
      ...item,
      interestPaymentId,
      documentCode
    }))
    
    console.log('付款从表数据:', paymentInfoList)
    console.log('付款退回从表数据:', refundInfoList)
    
    // 并行保存两个从表
    return Promise.all([
      pmInterestPaymentInfoSaveListAPI(paymentInfoList),
      pmInterestPaymentRefundInfoSaveListAPI(refundInfoList)
    ])
  })
  .then(() => {
    if (this.action.isCopy) {
      this.$message.success('操作成功')
    } else {
      this.$message.success(this.action.type == 'update' ? '编辑成功' : '添加成功')
    }
    this.close()
    this.$emit('save-success', { type: 'interestPayment' })
  })
  .catch(() => {
    this.loading = false
  })
}

三、遇到的问题

初期测试时,发现即便 interestRefundList(付款退回从表)有数据,但对应的保存接口 pmInterestPaymentRefundInfoSaveListAPI 并没有被调用,网络请求里也找不到对应的接口调用。

而付款明细接口 pmInterestPaymentInfoSaveListAPI 正常执行并保存成功。

这种情况让人非常困惑,因为:

  • 从表数据非空且正确;

  • 代码结构正确,两个接口调用写在 Promise.all 中;

  • 逻辑应该同时执行。

四、问题分析与定位

经过调试和排查,结合打印日志与断点观察,发现:

  1. 打印日志不输出付款退回从表数据,怀疑异步函数未进入退回分支;

  2. 退出当前页面后重新进入,问题消失,两个接口都能正常调用;

  3. 进一步确认是浏览器或前端框架的缓存导致数据未刷新,旧数据导致退回列表为空或接口调用跳过;

  4. 通过强制刷新数据、清除缓存、保证每次保存时 interestRefundList 都是最新且有数据,问题解决。

五、解决方案及细节

1. 保证数据实时性

确保每次调用保存前,this.interestRefundList 是通过接口或用户操作最新赋值的,避免被旧缓存覆盖。

// 确保数据获取逻辑
fetchRefundList(orderNumber).then(data => {
  this.interestRefundList = data || []
})

2. 打印调试

保存函数内部,加入打印,观察数据:

console.log('付款从表数据:', paymentInfoList)

console.log('付款退回从表数据:', refundInfoList)

确保打印时数据不为空。

3. 使用 Promise.all 并行执行接口

Promise.all 传入的数组中,所有接口都要是有效的 Promise,且参数有效

return Promise.all([ pmInterestPaymentInfoSaveListAPI(paymentInfoList), pmInterestPaymentRefundInfoSaveListAPI(refundInfoList) ])

如果某个参数为空数组或 null,有些接口实现会直接跳过请求,需注意。

4. 清除缓存和刷新页面测试

前端开发中常见“代码修改没生效”的原因是浏览器缓存,特别是 Service Worker、HTTP 缓存、Vue 组件缓存等。遇到接口未执行问题,可以尝试:

  • 退出登录重新登录;

  • 刷新页面,清除浏览器缓存(Ctrl+F5);

  • 关闭再打开页面;

  • 检查开发工具 Network 面板是否真的发送请求。


六、代码优化建议

  • 保存前判断从表数据是否为空,避免空数组调用接口:

const promises = []

if (paymentInfoList.length > 0) {
  promises.push(pmInterestPaymentInfoSaveListAPI(paymentInfoList))
}

if (refundInfoList.length > 0) {
  promises.push(pmInterestPaymentRefundInfoSaveListAPI(refundInfoList))
}

return Promise.all(promises)

  • 细化错误捕获,分别提示不同接口错误;

  • 添加加载状态控制,防止重复提交。


七、总结

  1. 主从表数据保存,推荐先保存主表拿到 ID,再给从表数据附加主表 ID,最后并行调用保存接口。

  2. Promise.all 可以并行等待多个接口,避免回调地狱。

  3. 遇到接口未调用,第一步检查数据是否为空,第二步检查参数格式,第三步排查缓存问题。

  4. 使用浏览器调试工具 Network 面板、Console 打印日志,逐步定位问题。

  5. 缓存问题常见于开发环境,重启、刷新、清缓存往往能解决。