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

如何创建从Apollo GraphQL Server取数的Ember Service?解决query报错

问题解决:Ember Service中使用ember-apollo-client报错this.apollo.query is not a function

错误原因

你在Service的constructor中直接调用queryManager()的方式错误——queryManager是ember-apollo-client提供的装饰器,并非普通可调用函数。直接调用无法生成关联Ember服务容器的有效Apollo实例,因此会出现query方法不存在的报错。同时,apollo.query返回异步Promise,直接赋值给属性会导致模板无法正常遍历数据。

修正方案

1. 修正Service代码

使用@queryManager装饰器注入Apollo实例,结合tracked属性存储异步查询结果,处理异步逻辑:

// app/services/nav-categories.js
import Service from '@ember/service';
import { queryManager } from "ember-apollo-client";
import { tracked } from '@glimmer/tracking';
import allCategories from "super-rentals/gql/queries/allCategories.graphql";

export default class NavCategoriesService extends Service {
  @queryManager apollo; // 用装饰器注入有效Apollo实例
  @tracked categories = []; // 用tracked属性存储查询结果,支持模板响应式更新

  async init() {
    super.init();
    try {
      const queryResult = await this.apollo.query({ query: allCategories });
      this.categories = queryResult.data.categories;
    } catch (error) {
      console.error('获取分类数据失败:', error);
    }
  }
}

如果需要更优雅的异步任务管理,也可以使用ember-concurrency的task:

// app/services/nav-categories.js
import Service from '@ember/service';
import { queryManager } from "ember-apollo-client";
import { tracked } from '@glimmer/tracking';
import { task } from 'ember-concurrency';
import allCategories from "super-rentals/gql/queries/allCategories.graphql";

export default class NavCategoriesService extends Service {
  @queryManager apollo;
  @tracked categories = [];

  fetchCategories = task(async () => {
    const result = await this.apollo.query({ query: allCategories });
    this.categories = result.data.categories;
  });

  init() {
    super.init();
    this.fetchCategories.perform(); // 初始化时执行查询任务
  }
}

2. 修正组件类名拼写错误

组件类名需与文件名匹配,否则可能导致服务注入异常:

// app/components/my-header.js
import Component from '@glimmer/component';
import { service } from '@ember/service';

export default class MyHeaderComponent extends Component { // 修正类名为MyHeaderComponent
  @service navCategories;
}

3. 模板无需修改

app/components/my-header.hbs的遍历逻辑可直接使用,因为this.navCategories.categories现在是响应式数组:

<ul>
{{#each this.navCategories.categories as |category|}}
  <li>{{category.name}}</li>
{{/each}}
</ul>

内容的提问来源于stack exchange,提问作者Raniere Silva

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 17:23:44