如何创建从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
相关产品推荐
相关产品推荐

