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

IndexedDB遍历关联表数据上传服务器时出现数据重复该如何解决

问题原因
  • 变量作用域冲突:你在全局定义了syncFormData,同时在SyncData的循环里又定义了同名局部变量,但getTable2、getTable3中访问的是全局的syncFormData。多个TableA行的异步处理流程并行执行,都会往同一个全局FormData里追加数据,导致前一次的残留数据被带到后一次的提交中,出现重复。
  • 数组取值错误:Array.filter()返回的是符合条件的数组,你直接用tblbData.Column1、tblbData.TableBId实际上取的是数组的属性,值为undefined,当关联多条数据时只会处理第一条甚至完全无法正确取值,变量混乱进一步加剧重复。
  • 异步时序混乱:$.each是同步执行的,会一次性触发所有TableA行的getTable2调用,但IndexedDB的读取是异步操作,回调触发顺序和循环顺序不一致,不同数据行的关联数据被交叉写入全局FormData,提交时混杂了多组数据。
  • 关联数据未遍历:TableB和TableC是一对多关系,你拿到过滤后的结果后没有循环遍历所有匹配行,只处理了第一条数据,遗漏的同时也会导致后续提交时残留之前的数据。
修复方案

核心思路是改用Promise+async/await控制异步时序,每个TableA行对应独立的FormData实例,避免数据交叉,同时遍历处理所有关联的子表数据。

  1. 改造IndexedDB取数方法为Promise风格,方便异步流程控制:
function getIndexeDbData(storeName) {
  return new Promise((resolve, reject) => {
    const myDB = window.indexedDB.open(dbName);
    myDB.onsuccess = function () {
      try {
        if (this.result.objectStoreNames.contains(storeName)) {
          this.result.transaction(storeName).objectStore(storeName).getAll().onsuccess = function (event) {
            resolve(event.target.result);
          };
        } else {
          resolve(false);
        }
      } catch (ex) {
        reject(ex);
      }
    };
    myDB.onerror = reject;
  })
}
  1. 重写同步逻辑,废弃全局FormData,按组处理关联数据:
async function SyncData() {
  const tableAData = await getIndexeDbData("TableA");
  if (!tableAData) return;
  // 按顺序逐行处理TableA数据,避免并行混乱
  for (const tblAData of tableAData) {
    // 每个TableA行对应独立的FormData,互不干扰
    const syncFormData = new FormData();
    syncFormData.append('TableA.Column1', tblAData.Column1);
    syncFormData.append('TableA.Column2', tblAData.Column2);
    // 组装当前TableA关联的所有子表数据
    await processTableB(tblAData.TableAId, syncFormData);
    // 单组数据组装完成后再提交
    await postToDb(syncFormData);
  }
}

async function processTableB(tableAId, syncFormData) {
  const allTableB = await getIndexeDbData("TableB");
  if (!allTableB) return;
  // 遍历当前TableA关联的所有TableB行
  const matchedTableB = allTableB.filter(x => x.TableAId === tableAId);
  for (const tblbData of matchedTableB) {
    syncFormData.append('TableB.Column1', tblbData.Column1);
    syncFormData.append('TableB.Column2', tblbData.Column2);
    // 组装当前TableB关联的TableC数据
    await processTableC(tblbData.TableBId, syncFormData);
  }
}

async function processTableC(tableBId, syncFormData) {
  const allTableC = await getIndexeDbData("TableC");
  if (!allTableC) return;
  // 遍历当前TableB关联的所有TableC行
  const matchedTableC = allTableC.filter(x => x.TableBId === tableBId);
  for (const tblCData of matchedTableC) {
    syncFormData.append('TableC.Column1', tblCData.Column1);
    syncFormData.append('TableC.Column2', tblCData.Column2);
  }
}

// 改造提交方法,接收FormData参数并返回Promise
function postToDb(syncFormData) {
  return new Promise((resolve, reject) => {
    $.ajax({
      url: '你的服务端提交接口地址',
      type: 'POST',
      data: syncFormData,
      processData: false,
      contentType: false,
      success: resolve,
      error: reject
    })
  })
}
  1. 可选优化:如果数据量较大,可以给TableB的TableAId、TableC的TableBId建立IndexedDB索引,直接用索引查询对应数据,不需要每次全表扫描过滤,能大幅提升查询效率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 01:45:04