Как заставить find() принимать массив вместо одного объекта?
Используя JS-Data 2.6 в Angular, я пытаюсь загрузить массив данных, используя хороший чистый URL, например /report/22. (Этот формат имеет смысл, потому что он следует бизнес-логике - я загружаю данные отчета по идентификатору категории и получаю несколько строк назад.)
Тем не мение,
- когда я использую
find
то js-данные умирают с ужасом[Error] "attrs" must be an object!
потому что он ожидает 1 строку, и не может быть убежден иначе - если я что-то упустил. - когда я использую
findAll
, то мне нужно искать, используя более уродливый/report/?categoryId = 22
- и поменяй сервер - когда я использую действия, он добавляет имя действия в URI, который мне не нужен, например,
/report/22/myaction
Есть ли способ использовать либо find() или findAll(), чтобы
- иметь чистый URL
- загрузить массив данных
- желательно, не меняя реализацию сервера
1 ответ
Все в этом ответе предполагает, что вы используете HTTP-адаптер.
Стандартные требования JSData следующие:
GET /<resource>/:id
возвращает объект, например{ id: 1 }
GET /<resource>
возвращает массив объектов, например[{ id: 1 }, { id: 2 }]
POST /<resource> { some: 'field' }
создает один элемент в вашей базе данных и возвращает обновленный элемент, например{ id: 1, some: 'field' }
PUT /<resource>/:id { updated: 'field' }
обновляет один элемент в вашей базе данных и возвращает обновленный элемент, например,{ id: 1, updated: 'field' }
PUT /<resource> { updated: 'field' }
обновляет коллекцию элементов в вашей базе данных и возвращает обновленные элементы, например[{ id: 1, updated: 'field' }, { id: 2, updated: 'field' }]
-DELETE /<resource>/:id
удаляет один элемент из вашей базы данныхDELETE /<resource>
удаляет коллекцию предметов из вашей базы данных
По умолчанию, DS#find
делает GET /<resource>/:id
, а также DS#findAll
делает GET /<resource>
,
Любой ответ от сервера должен быть в правильном формате к моменту получения DS#inject
,
Жизненный цикл для этих вызовов следующий:
- Вызов
find
или жеfindAll
метод адаптера- Вызов
GET
метод адаптера - Вызов
HTTP
метод адаптера - Вызов
deserialize
метод ответа сервера
- Вызов
- Передайте ответ адаптера на
afterFind
или жеafterFindAll
крюк - Проверьте
cacheResponse
- Если
true
передать результатafterFind
или жеafterFindAll
вDS#inject
- Если
false
передать результатafterFind
или жеafterFindAll
вDS#createInstance
- Если
- Вернуть окончательный результат
Единственный способ избежать ошибки внедрения - это либо:
А) Не вводить ответ адаптера в хранилище данных
или же
Б) Массаж данных в правильном формате, прежде чем они передаются в DS#inject
DS#inject
требует либо объект, который имеет поле, указанное ресурсом idAttribute
вариант или массив того же самого.
У вас есть три возможности массировать данные, прежде чем они попадут в DS#inject
:
- Перехватчик ответа HTTP
-
deserialize
крюк -
afterFind
или жеafterFindAll
крюк
В любом из этих методов вы можете исправить данные DS#inject
надеется.
Если вы хотите быть в состоянии сделать Report.find(22)
тогда вы можете сделать:
var Report = store.defineResource({
name: 'report',
afterFind: function (Report, data, cb) {
cb(null, {
id: 22,
data: data
});
}
});
Report.find(22).then(function (report) {
report.id; // 22
report.data; // [{...}, {...}]
});
Все это предполагает, что вы действительно хотите иметь возможность использовать DS#find
, но DS#find
а также DS#findAll
предназначены для использования с ресурсами RESTful, где ресурс соответствует таблице в базе данных, а экземпляры ресурса соответствуют строкам в таблице. Генерация отчетов обычно является одной из тех вещей, когда вы собираете данные из разнородных источников, выполняете агрегацию и т. Д. Это не так предсказуемо (и, следовательно, этот вопрос).
Вот еще один вариант:
var Report = store.defineResource({
name: 'report',
/* Static Class Methods */
findByCategoryId: function (id) {
// Use the adapter directly
return Report.getAdapter('http').find(Report, id).then(function (data) {
// Inject the result into the store
return Report.inject({
id: 22,
data: data
});
});
}
});
Report.findByCategoryId(22). then(function (report) {
return Report.findByCategoryId(23);
}).then(function (report) {
Report.filter(); // [{...}, {...}]
});
В принципе, есть много способов выполнить любую конкретную задачу, каждый со своим набором плюсов / минусов. JSData может обобщать только многие варианты использования со своими настройками по умолчанию.
Чтобы раскрыть возможности JSData и максимизировать свою производительность, вы должны принять во внимание множество опций и приемов в JSData, которые позволяют вам формировать JSData по своему вкусу. Если вы обнаружите, что любое конкретное расширение или настройка, которую вы написали, может быть обобщено и принесет пользу многим другим, имеющим такой же вариант использования, дайте нам знать!
Ура!