Ember.js 3.24 LTS 组件如何实现API轮询并更新活动日志展示
问题根源
你当前的轮询逻辑仅在路由model钩子执行时返回了首次拉取的日志数据,后续递归调用pollTestActivity拿到的新数据没有同步到路由的响应式属性中,组件接收的@phaseActivityLog始终是初始的旧引用,因此不会触发视图更新。
代码修改方案
1. 调整路由逻辑
// addon/routes/single-scan/index.js import { later, cancel } from '@ember/runloop'; ... async model() { // 首次拉取初始数据 let phaseActivityLog = await this.store.query('phase-activity-log', testId, { reload: true }); return { phaseActivityLog }; } setupController(controller, model) { super.setupController(...arguments); // 将初始数据挂载到controller的响应式属性上 controller.phaseActivityLog = model.phaseActivityLog; // 启动轮询任务 this._startPolling(testId); } // 私有轮询方法 async _startPolling(testId) { this.pollTimer = later( this, async function () { // 拉取最新日志数据 const latestLogs = await this.store.query('phase-activity-log', testId, { reload: true }); // 更新controller属性,自动触发响应式更新 this.controller.set('phaseActivityLog', latestLogs); // 触发下一轮轮询 this._startPolling(testId); }, 2000 ); } // 路由离开时清理定时器,避免内存泄漏 deactivate() { super.deactivate(...arguments); if (this.pollTimer) { cancel(this.pollTimer); this.pollTimer = null; } }
2. 修改路由模板传参
将路由模板中传给组件的参数从model.phaseActivityLog改为controller上的响应式属性:
// addon/templates/single-scan/index.hbs <SingleScan::PhaseActivityLog @phaseActivityLog={{this.phaseActivityLog}} />
3. 组件代码无需改动
你现有的组件模板逻辑可以直接复用,@phaseActivityLog更新后{{each}}会自动重新渲染最新的日志列表。
补充说明
如果你使用Ember Data且查询参数固定,store.query返回的RecordArray本身是动态响应式的,只要后台返回新数据,数组内的记录会自动更新,不需要每次替换整个数组引用,也能触发组件重渲染。上述方案是更通用的实现,兼容所有数据结构场景。
内容的提问来源于stack exchange,提问作者RonPringadi
相关产品推荐
相关产品推荐

