使用ember-api-actions的collectionAction报错:Cannot read property 'constructor' of undefined
解决Ember-api-actions调用collectionAction时的"Cannot read property 'constructor' of undefined"错误
你踩了ember-api-actions里一个容易混淆的核心点:collectionAction是挂载在模型类上的静态方法,而非模型实例的方法。你现在试图从模型实例(通过changeset获取)调用download(),但这个方法根本不存在于实例上,所以才会抛出这个错误。
下面分两种场景给出针对性解决方案:
场景1:这个download动作确实是集合级别的(比如获取全量mailbox的问候文件)
如果/mailboxes/greeting是针对整个资源集合的接口,你需要从模型类而非实例调用这个方法。在组件里可以这样修改:
方法A:直接导入模型类调用
// 组件顶部导入mailbox模型(注意路径要匹配你的项目结构) import Mailbox from '../models/mailbox'; // 在toggle action里替换原有的download调用逻辑: Mailbox.download().then((content) => { this.saveFileAs(this.get('filename'), content, this.get('contentType')) })
方法B:通过store动态获取模型类调用
如果你不想硬编码模型路径,也可以通过Ember Data的store来获取模型类:
// 在toggle action里: this.store.modelFor('mailbox').download().then((content) => { this.saveFileAs(this.get('filename'), content, this.get('contentType')) })
场景2:这个download动作是针对单个mailbox实例的(比如获取当前mailbox的专属问候文件)
如果greeting接口属于单个mailbox(比如路径是/mailboxes/:id/greeting),那你需要把模型里的collectionAction改成instanceAction:
// mailbox模型修改: import DS from 'ember-data' import { instanceAction } from 'ember-api-actions' // 替换成instanceAction export default DS.Model.extend({ mailbox: DS.attr(), //display only pin: DS.attr(), download: instanceAction({ path: 'greeting'}) // 这里改为instanceAction })
之后在组件里,确保从有效的模型实例调用方法——如果changeset正确包裹了模型实例,可继续用this.get('changeset').download(),但更稳妥的方式是直接获取原始模型实例:
this.get('model').download().then((content) => { this.saveFileAs(this.get('filename'), content, this.get('contentType')) })
额外检查点
- 确认ember-api-actions版本与当前Ember版本兼容,部分旧版本在处理changeset代理时可能存在问题;
- 检查接口返回的content格式是否符合
saveFileAs的要求,避免后续出现文件保存失败的问题。
内容的提问来源于stack exchange,提问作者Nick Shcherba
相关产品推荐
相关产品推荐

