如何为 ember.js 创建自定义适配器?

Posted

技术标签:

【中文标题】如何为 ember.js 创建自定义适配器?【英文标题】:How do you create a custom adapter for ember.js? 【发布时间】:2013-07-30 02:01:47 【问题描述】:

我计划使用 ember.js,但是我的 REST api 与打包的 REST 适配器并不完全一致。我想“覆盖” find 并能够将我自己的 ajax 放入其中。我不喜欢 ember findAll 如何在没有分页选项的情况下检索我的所有文档,因此与其他查询参数一起使用会很有用——这就是我想编写自己的 ajax 的原因。我一直找不到任何有关如何执行此操作的文档。

【问题讨论】:

【参考方案1】:

对于 Ember 数据

这是 Ember Data 1.0 beta 9 的最新版本。

扩展 Ember 数据适配器之一。使其在站点范围内:

App.ApplicationAdapter = DS.RESTAdapter.extend(....

使其特定于模型:

App.FooAdapter = DS.RESTAdapter.extend(...

然后您将定义您想要覆盖的实现。您始终可以选择调用 this._super 并恢复到基本实现。例如

App.NotesAdapter = DS.RESTAdapter.extend(
  find: function(store, type, id) 
    id = "foo" + id;
    return this._super(store, type, id);
  
);

或者您可以完全覆盖实现:

App.NotesAdapter = DS.RESTAdapter.extend(
  find: function(store, type, id) 
    // Do your thing here
    return this.ajax(this.buildURL(type.typeKey, id), 'GET');
  ,

  findAll: function(store, type, sinceToken) 
    // Do your thing here
    var query;

    if (sinceToken) 
      query =  since: sinceToken ;
    

    return this.ajax(this.buildURL(type.typeKey), 'GET',  data: query );
  ,

  findQuery: function(store, type, query) 
    // Do your thing here
    return this.ajax(this.buildURL(type.typeKey), 'GET',  data: query );
  ,

  findMany: function(store, type, ids, owner) 
    return this.ajax(this.buildURL(type.typeKey), 'GET',  data:  ids: ids  );
  ,
   .....
);

要查看完整的 api,您可以覆盖:http://emberjs.com/api/data/classes/DS.RESTAdapter.html

序列化器

通常更重要的是滚动您自己的序列化程序来处理数据以适应您的休息端点。以下是过渡文档https://github.com/emberjs/data/blob/master/TRANSITION.md 中的一些有用信息。

简短的版本是,一旦 Ajax 请求完成,生成的有效负载将通过以下钩子发送:

    如果原始请求是针对单个记录(例如 find/save),则有效负载将发送到 extractSingle;如果原始请求针对记录数组(例如 findAll/findQuery),则将负载发送到 extractArray 这些方法的默认行为是将负载的顶层拆分为多个较小的记录。 这些较小的记录中的每一个都被发送到规范化,这可以一次对一条记录进行规范化。 最后,可以对特定类型的记录进行特殊规范化。
App.PostSerializer = DS.RESTSerializer.extend( extractSingle:函数(存储,类型,有效负载,ID) // 按摩 this._super(store, type, payload, id); , extractArray:函数(存储,类型,有效负载) // 按摩 this._super(store, type, payload); , 规范化:函数(类型,哈希,属性) // 按摩 this._super(类型,哈希,属性); ); 当您的有效负载的***组织方式与 Ember Data 预期的不同时,请使用 extractSingle 和 extractArray 如果有效载荷中的所有子哈希都可以以相同的方式进行归一化,则使用 normalize 对子哈希进行归一化。 使用 normalizeHash 规范化特定子哈希。 确保在覆盖 extractSingle、extractArray 或 normalize 时调用 super,以便调用链的其余部分。

自己动手

App.FooAdapter = Ember.Object.extend(
  find: function(id)
    return $.getJSON('http://www.foolandia.com/foooo/' + id);
  
);

然后从你的路线,或任何地方

App.FooRoute = Ember.Route.extend(
  model: function()
    var adapter = App.FooAdapter.create();
    return adapter.find(1);
  
);

现在我个人会将适配器注入到路由中,只是为了让我的生活更轻松:

App.initializer(
    name: "fooAdapter",

    initialize: function (container, application) 
        application.register("my:manager", application.FooAdapter);
        application.inject("controller", "fooAdapter", "my:manager");
        application.inject("route", "fooAdapter", "my:manager");
    
);

然后在路线上你可以更懒一点:

App.FooRoute = Ember.Route.extend(
  model: function()
    return this.fooAdapter.find(1);
  
);

例如:http://emberjs.jsbin.com/OxIDiVU/676/edit

您可以在没有 Ember 数据的情况下阅读有关 Ember 的更多信息:Ember without Ember Data

【讨论】:

你不需要revision: 13 谢谢,我实际上使用的是 ember 模型而不是 ember-data,所以我对商店等不熟悉。 这太好了,Ember.Adapter 中实现的方法都是这些吗?我找不到任何余烬数据。只是在基本适配器中使用的方法,还是我会推出全新的方法? ember-data 的文档在哪里? 这个答案已经过时了。 Ember Data 在稳定发布的过程中经历了重大变化。 它并不声称是最新版本的最新版本,它从一开始就有一个版本。而且稳定性方面,现在和年初一样稳定,主要是功能游戏,还有json api。【参考方案2】:

我遇到了同样的问题。我也想在我的后端(cakephp)中使用稍微不同的格式,但不知道该怎么做。前面的答案很好,但您可能不需要重新定义每个方法,只需通过覆盖 RESTAdapter 中的 buildURL 来更改 URL 的格式。

例如,我想使用 cakePHP 的扩展并希望我的 url 在应用程序范围内看起来像这样:

/users.json (findAll) /users/view/1.json(查找) /users/delete/1.json /users/edit.json (POST) /users/add.json (POST)

经过大量拉扯并意识到 ember-data 是必不可少的,我使用了以下代码:

App.ApplicationAdapter = DS.RESTAdapter.extend(
  buildURL: function(type, id) 
    var url = '/' + this.pluralize(type.typeKey);

    if (id) 
        url += '/' + id;
    

    url += '.json';

    return url;
  
);

Ember 的文档很好,但他们的大多数示例都使用 FIXTURE 数据。我希望他们有一个简单的例子,如何针对不同的情况编写不同类型的适配器。

【讨论】:

在您的案例中,您是如何解决 HTTP 方法替换的?我的意思是“/users/edit.json (POST)”。用于修改的默认 ember HTTP 方法是 PUT。【参考方案3】:

对于那些自己编写适配器的人,如果您需要从适配器返回一个值(例如,userId),您可以返回 json 或 promise。这是返回承诺的示例:

App.RequestAdapter = Ember.Object.extend(
    newRequest: function (data) 
        return new Ember.RSVP.Promise(function (resolve, reject) 
            Ember.$.ajax(
                type: 'POST',  // method post
                url: '/Request/Create', //target url
                data: JSON.stringify(data), //the JSON.stringify converts data to JSON
                dataType: "json",
                contentType: "application/json; charset=utf-8",
                success: function (response) 
                    resolve(response);
                ,
                error: function (reason) 
                    reject(reason);
                
            );
        );
    
);

//use this adapter in  your controller
var adapter = App.RequestAdapter.create();

adapter.newRequest(data).then(function (response)    //newRequest is method of our adapter
    console.log(response.userId);  //specify response data
, function(error)
    //handle error  
);

您可以在此处获取有关 Ember 承诺的更多信息:https://hackhands.com/3-ways-ember-js-leverages-promises/ 或此处http://emberjs.com/api/classes/RSVP.Promise.html

【讨论】:

以上是关于如何为 ember.js 创建自定义适配器?的主要内容,如果未能解决你的问题,请参考以下文章

如何为列表视图创建自定义光标适配器以用于图像和文本?

如何为随机自定义 ListView 适配器设置按钮单击事件?

Ember 关系在测试环境中不尊重模型自定义适配器

如何为 Scoped Allocator 模型启用自定义容器

如何为自定义控件创建事件

如何为 iPhone 创建自定义 Interface Builder 插件?