如何动态更新Firebase快照监听器where查询条件以降低资源用量
实现方案
快照监听器创建后查询条件就会固定,无法动态修改参数,你需要在每次更新MAX_UPDATED_TIME_VISITOR后卸载旧监听器,用新的时间戳重新创建监听器即可实现需求。
1. 完整实现代码
首先定义全局变量存储监听器卸载函数与最新时间戳,封装单独的监听器初始化方法:
// 存储最新时间戳,初始值可从本地持久化存储读取,避免每次打开应用全量拉取数据 let MAX_UPDATED_TIME_VISITOR = Number(localStorage.getItem('max_updated_time')) || 0; // 存储监听器卸载函数 let unsubscribeListListener = null; function initListListener() { // 先卸载旧监听器,避免重复触发回调 if (unsubscribeListListener) { unsubscribeListListener(); } const db = this.getFirestore(); // 用最新的时间戳创建查询 unsubscribeListListener = db.collection("collection1") .doc("doc1") .collection("list") .where('updatedOn', '>=', MAX_UPDATED_TIME_VISITOR) .onSnapshot((datas) => { let currentMax = MAX_UPDATED_TIME_VISITOR; // 仅处理发生变更的文档,无需遍历全部返回结果 datas.docChanges().forEach((change) => { const mainData = change.doc.data(); // 此处添加你的业务逻辑,分别处理新增、修改、删除的文档 switch(change.type) { case 'added': // 处理新增文档 break; case 'modified': // 处理修改文档 break; case 'removed': // 处理删除文档 break; } // 更新最大时间戳 if (mainData.updatedOn > currentMax) { currentMax = mainData.updatedOn; } }); // 时间戳有更新时,持久化存储并重建监听器 if (currentMax !== MAX_UPDATED_TIME_VISITOR) { MAX_UPDATED_TIME_VISITOR = currentMax; localStorage.setItem('max_updated_time', MAX_UPDATED_TIME_VISITOR); initListListener(); } }); } // 应用初始化时调用一次即可 initListListener();
2. 常见问题说明
- 读取量计费说明:Firestore按服务端实际返回的文档数计费,重建监听器后服务端仅会返回符合新查询条件的文档,已经拉取过的旧文档不会重复返回,不会产生额外计费。
- fromCache始终为false的原因:默认配置下只要客户端有可用网络,监听器会优先从服务端同步数据,因此
metadata.fromCache会始终返回false,该字段不影响实际的变更监听逻辑,无需特殊处理。 - 索引要求:使用
updatedOn作为查询条件需要先给对应集合创建单字段索引,首次运行如果控制台报索引缺失错误,点击报错中的链接即可自动创建。
内容的提问来源于stack exchange,提问作者Intellial solutions
相关产品推荐
相关产品推荐

