Ember中如何判断peekAll是否返回了模型?
解决Ember Data中query请求的缓存与peekAll判断问题
首先,你遇到的.content.length问题是因为peekAll返回的是DS.RecordArray,content是Ember Data内部的私有属性,不应该直接访问。正确的做法是用length属性(Ember 3.x+支持直接点访问,低版本用get('length'))来判断是否有记录:
let positions = this.store.peekAll('position'); if (positions.length === 0) { // 这里发起API请求 }
不过这只是判断本地有没有任何position记录,而你用的是query(带特定条件的查询),Ember Data默认不会像findAll那样自动缓存query的结果,每次调用都会发起新请求,所以需要手动实现符合你查询条件的缓存逻辑:
方案一:手动筛选本地缓存记录
如果你的查询条件比较简单(比如等于某个字段值),可以先从本地store中筛选出符合条件的记录,再决定是否发起请求:
// 假设你的查询条件是 { department: 'engineering' } const queryParams = { department: 'engineering' }; // 从本地缓存筛选符合条件的记录 const cachedPositions = this.store.peekAll('position').filter(record => { return record.get('department') === queryParams.department; }); if (cachedPositions.length === 0) { // 没有符合条件的缓存记录,发起API请求 return this.store.query('position', queryParams).then(positions => { // 处理返回的数据 return positions; }); } else { // 使用本地缓存的记录 return cachedPositions; }
这种方式适合简单的查询逻辑,但如果你的查询涉及后端复杂处理(比如分页、模糊搜索、多条件组合),本地筛选可能和后端结果不一致,这时候可以用下面的方案。
方案二:用自定义服务缓存查询结果
创建一个专门的缓存服务,把query的结果按查询参数缓存起来,避免重复请求:
首先创建缓存服务:
// app/services/query-cache.js import Service from '@ember/service'; export default class QueryCacheService extends Service { // 用Map存储缓存,key是字符串化的查询参数,value是查询结果 cache = new Map(); getCachedQuery(store, modelName, query) { const cacheKey = JSON.stringify({ modelName, query }); // 检查缓存中是否已有结果 if (this.cache.has(cacheKey)) { return Promise.resolve(this.cache.get(cacheKey)); } // 没有缓存就发起请求,并存入缓存 return store.query(modelName, query).then(results => { this.cache.set(cacheKey, results); return results; }); } // 可选:提供清空缓存的方法,当数据更新时调用 clearCache(modelName, query) { const cacheKey = JSON.stringify({ modelName, query }); this.cache.delete(cacheKey); } }
然后在路由中使用这个服务:
// app/routes/your-route.js import Route from '@ember/routing/route'; import { inject as service } from '@ember/service'; export default class YourRoute extends Route { @service queryCache; model() { const queryParams = { department: 'engineering' }; // 先检查本地有没有符合条件的记录 const cachedRecords = this.store.peekAll('position').filter(record => { return record.get('department') === queryParams.department; }); if (cachedRecords.length > 0) { return cachedRecords; } // 没有的话调用缓存服务发起请求 return this.queryCache.getCachedQuery(this.store, 'position', queryParams); } }
注意事项
- 当你的
position记录有更新、新增或删除时,记得调用clearCache方法清空对应查询的缓存,避免展示过时数据。 - 如果你的查询参数包含动态值(比如当前用户ID),字符串化后的key会自动区分不同的查询,不用担心缓存混淆。
内容的提问来源于stack exchange,提问作者user6506263
相关产品推荐
相关产品推荐

