Dexie中Table.bulkPut方法的.then()回调返回值是什么?
Dexie bulkPut/bulkAdd 返回值规则说明
核心结论
你对bulkAdd的预期符合设计逻辑,对bulkPut的预期不符合Dexie的原生规则,你实际遇到的返回仅2个主键的现象是旧版本Dexie的正常表现。
1. Table.bulkAdd() 行为规则
当配置{allKeys: true}且未开启failOnDuplicate时:
- 冲突的主键(也就是你例子中已存在的3、5)会被自动跳过,不会修改原有记录
- 最终返回值仅包含成功新增的记录主键,对应你例子中的
[2,4],最终本地表数据为[1,2,3,4,5],和你的预期完全一致。
2. Table.bulkPut() 行为规则
Dexie对bulkPut的返回值规则在2.x和3.x+版本有差异:
3.x及以上新版本规则
- 开启
{allKeys: true}时,返回数组长度和输入数组完全一致,顺序也一一对应,每个位置的值为对应输入记录最终在表中的主键 - 不会校验记录内容是否实际变更:只要主键存在,无论内容和原有数据是否相同,都会视为操作成功,返回对应主键
- 对应你的例子,返回值为
[2,3,4,5]
2.x及更早旧版本规则
- 开启
{allKeys: true}时,仅返回新增成功的记录主键,更新、无变更的记录主键不会被纳入返回结果 - 对应你的例子,返回值为
[2,4],就是你实际遇到的现象
自定义实现需求方案
如果你需要拿到「仅实际发生新增/修改操作的记录主键」,可以通过以下代码自行实现:
/** * 执行bulkPut并返回实际发生变更的主键 * @param {Dexie.Table} table 操作的Dexie表实例 * @param {Array} items 要写入的记录数组,假设主键字段为id * @returns {Promise<Array>} 实际新增/修改的主键列表 */ async function bulkPutGetChangedKeys(table, items) { const inputIds = items.map(item => item.id); // 查询已存在的记录主键和对应内容 const existingRecords = await table.where('id').anyOf(inputIds).toArray(); const existingMap = new Map(existingRecords.map(record => [record.id, record])); // 执行bulkPut await table.bulkPut(items); // 筛选出新增或内容有变更的主键 const changedKeys = items.reduce((res, item) => { const existing = existingMap.get(item.id); // 新增记录 或 内容和原有记录不一致 if (!existing || JSON.stringify(existing) !== JSON.stringify(item)) { res.push(item.id); } return res; }, []); return changedKeys; }
注:上述代码中的内容对比逻辑可根据你的业务场景调整,避免JSON.stringify的性能和边界情况问题
内容的提问来源于stack exchange,提问作者Louwrens
相关产品推荐
相关产品推荐

