You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在控制器中解析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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:05:58