Я планирую использовать ember.js, однако мой REST api точно не согласуется с упакованным адаптером REST. Я хотел бы "переопределить" поиск и уметь вставлять в него свой собственный аякс. Мне не нравится, как ember findAll извлекает все мои документы без параметров для разбивки на страницы, так что наряду с другими параметрами запроса было бы полезно - именно поэтому я хочу написать свой собственный ajax. Я не смог найти документацию о том, как я буду заниматься этим.
Как создать пользовательский адаптер для ember.js?
Ответ 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