Как заставить 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,

Жизненный цикл для этих вызовов следующий:

  1. Вызов find или же findAll метод адаптера
    1. Вызов GET метод адаптера
    2. Вызов HTTP метод адаптера
    3. Вызов deserialize метод ответа сервера
  2. Передайте ответ адаптера на afterFind или же afterFindAll крюк
  3. Проверьте cacheResponse
    1. Если true передать результат afterFind или же afterFindAll в DS#inject
    2. Если false передать результат afterFind или же afterFindAll в DS#createInstance
  4. Вернуть окончательный результат

Единственный способ избежать ошибки внедрения - это либо:

А) Не вводить ответ адаптера в хранилище данных

или же

Б) Массаж данных в правильном формате, прежде чем они передаются в DS#inject

DS#inject требует либо объект, который имеет поле, указанное ресурсом idAttribute вариант или массив того же самого.

У вас есть три возможности массировать данные, прежде чем они попадут в DS#inject:

  1. Перехватчик ответа HTTP
  2. deserialize крюк
  3. 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 по своему вкусу. Если вы обнаружите, что любое конкретное расширение или настройка, которую вы написали, может быть обобщено и принесет пользу многим другим, имеющим такой же вариант использования, дайте нам знать!

Ура!

Другие вопросы по тегам