Подтвердить что ты не робот

Как создать пользовательский адаптер для ember.js?

Я планирую использовать ember.js, однако мой REST api точно не согласуется с упакованным адаптером REST. Я хотел бы "переопределить" поиск и уметь вставлять в него свой собственный аякс. Мне не нравится, как ember findAll извлекает все мои документы без параметров для разбивки на страницы, так что наряду с другими параметрами запроса было бы полезно - именно поэтому я хочу написать свой собственный ajax. Я не смог найти документацию о том, как я буду заниматься этим.

4b9b3361

Ответ 1

Для данных Ember

Это актуально с Ember Data 1.0 beta 9.

Расширьте один из Ember Data Adapters. Чтобы сделать его сайт широким:

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

Serializer

Часто важнее будет использовать собственный сериализатор для массирования данных в соответствии с конечной точкой отдыха. Вот некоторая полезная информация из переходного документа https://github.com/emberjs/data/blob/master/TRANSITION.md.

Короткий вариант заключается в том, что после завершения запроса Ajax полученная полезная нагрузка отправляется через следующие перехватчики:

  • Полезная нагрузка отправляется в extractSingle, если исходный запрос был для одной записи (например, find/save) или extractArray, если исходный запрос был для массива записей (например, findAll/findQuery)
  • Поведение этих методов по умолчанию состоит в том, чтобы разделить верхний уровень полезной нагрузки на несколько меньших записей.
  • Каждая из этих меньших записей отправляется для нормализации, что может нормализовать запись за раз.
  • Наконец, конкретные типы записей могут быть специально нормализованы.
    App.PostSerializer = DS.RESTSerializer.extend({
      extractSingle: function(store, type, payload, id) {
        // massage
        this._super(store, type, payload, id);
      },
      extractArray: function(store, type, payload) {
        // massage
        this._super(store, type, payload);
      },
      normalize: function(type, hash, property) {
        // massage
        this._super(type, hash, property);
      }
    });
  • используйте extractSingle и extractArray, когда верхний уровень вашей полезной нагрузки организован иначе, чем Ember Data ожидает
  • используйте нормализацию для нормализации суб-хэшей, если все под-хэши в полезной нагрузке могут быть нормализованы одинаково.
  • используйте normalizeHash для нормализации определенных суб-хэшей.
  • обязательно вызовите super, если вы переопределите extractSingle, extractArray или нормализуете, чтобы остальная цепочка получила вызов.

Перемещение ваших собственных

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 Data: Эмбер без данных Ember

Ответ 2

У меня была та же проблема. Я тоже хотел использовать немного другой формат с моим backend (cakePHP) и не мог понять, как это сделать. Предыдущие ответы велики, но вам не нужно переопределять каждый метод, но просто изменять формат URL-адреса, переопределяя buildURL в RESTAdapter.

Например, я хочу использовать расширение cakePHP и хочу, чтобы мои URL-адреса выглядели так: Application wide:

  • /users.json(findAll)
  • /users/view/1.json(найти)
  • /users/delete/1.json
  • /users/edit.json(POST)
  • /users/add.json(POST)

После многократного вытягивания волос и осознания того, что данные ember необходимы, я использовал следующий код:

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. Мне жаль, что у них не было простого примера, как писать различные типы адаптеров для разных ситуаций.

Ответ 3

Для тех, кто сам кодирует адаптер, если вам нужно вернуть значение из вашего адаптера (например, userId), вы можете либо вернуть json, либо обещать. Вот пример возврата обещания:

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 promises здесь: https://hackhands.com/3-ways-ember-js-leverages-promises/ или здесь http://emberjs.com/api/classes/RSVP.Promise.html