如何在控制器中解析Promise?及Ember模型关联与模板问题
问题解答
1. 如何在Ember控制器中解析Promise?
在Ember里处理Promise有几种实用方式,根据你的Ember版本选合适的就行:
方法一:.then()链式调用(兼容全版本)
如果是在控制器的action里获取数据或处理异步操作,用.then()处理成功状态,.catch()捕获错误:
// app/controllers/xxx.js import Controller from '@ember/controller'; import { inject as service } from '@ember/service'; export default class XxxController extends Controller { @service store; actions = { fetchModelA(id) { this.store.findRecord('modelA', id) .then(modelA => { // Promise解析成功后的逻辑 this.set('selectedModelA', modelA); }) .catch(error => { // 错误处理 console.error('获取modelA失败:', error); }); } }; }
方法二:async/await(现代Ember推荐)
Ember Octane及以后版本支持async/await,代码更简洁易读:
// app/controllers/xxx.js import Controller from '@ember/controller'; import { inject as service } from '@ember/service'; import { action } from '@ember/object'; export default class XxxController extends Controller { @service store; @action async fetchModelA(id) { try { const modelA = await this.store.findRecord('modelA', id); this.set('selectedModelA', modelA); } catch (error) { console.error('获取modelA失败:', error); } } }
方法三:计算属性中解析异步关联
如果要在计算属性里处理异步关联(比如modelA的modelBs),可以结合@cached装饰器和async/await:
// app/controllers/xxx.js import Controller from '@ember/controller'; import { cached } from '@glimmer/tracking'; export default class XxxController extends Controller { @cached async get resolvedModelBs() { // 等待异步关联解析完成 return await this.model.modelA.modelBs; } }
然后在模板里用{{#await}}助手处理Promise:
{{#await this.resolvedModelBs}} {{#each this.resolvedModelBs as |modelB|}} {{modelB.status}} {{/each}} {{else}} 加载中... {{/await}}
2. 模板中访问modelA关联的modelB计算属性问题
首先要纠正你代码里的一个小错误:modelB中的statusOne和statusTwo计算属性写法不对。filterBy是用来过滤数组的,但status是单个字符串属性,不能直接用这个方法。我们先修正这个问题,再解决模板访问的问题。
步骤一:修正modelB的计算属性
如果是想判断当前modelB的status是否为'one'或'two',应该用直接比较或者equal逻辑:
// app/models/modelB.js import Model, { attr, belongsTo } from '@ember-data/model'; export default class ModelBModel extends Model { @belongsTo('modelA', { async: true }) modelA; @attr('string') status; // 判断当前modelB的status是否为'one' get isStatusOne() { return this.status === 'one'; } // 判断当前modelB的status是否为'two' get isStatusTwo() { return this.status === 'two'; } }
步骤二:如果需要过滤modelA下的modelBs(按status)
如果你的需求是从modelA中筛选出status为'one'或'two'的modelBs,应该在modelA上定义计算属性:
// app/models/modelA.js import Model, { attr, hasMany } from '@ember-data/model'; import { cached } from '@glimmer/tracking'; export default class ModelAModel extends Model { @hasMany('modelB', { async: true }) modelBs; // 筛选status为'one'的modelBs @cached async get modelBsStatusOne() { const allModelBs = await this.modelBs; return allModelBs.filterBy('status', 'one'); } // 筛选status为'two'的modelBs @cached async get modelBsStatusTwo() { const allModelBs = await this.modelBs; return allModelBs.filterBy('status', 'two'); } }
步骤三:模板中正确访问关联数据
由于modelBs是异步关联,遍历modelAs时需要用{{#await}}助手等待Promise解析,再访问属性:
{{#each @modelAs as |modelA|}} <div>{{modelA.someAttribute}}</div> <!-- 展示当前modelA的所有modelBs --> <h4>所有ModelB</h4> {{#await modelA.modelBs}} {{#each modelA.modelBs as |modelB|}} <p>状态:{{modelB.status}} {{#if modelB.isStatusOne}}(状态一){{/if}}</p> {{/each}} {{else}} <p>加载ModelB数据中...</p> {{/await}} <!-- 展示当前modelA中status为'one'的modelBs --> <h4>状态为One的ModelB</h4> {{#await modelA.modelBsStatusOne}} {{#each modelA.modelBsStatusOne as |modelB|}} <p>{{modelB.status}}</p> {{/each}} {{else}} <p>加载筛选数据中...</p> {{/await}} {{/each}}
内容的提问来源于stack exchange,提问作者Mikelemuel
相关产品推荐
相关产品推荐

