0

在 Angular 中使用 JS-Data 2.6,我正在尝试使用干净的 URL 加载数据数组,例如 /report/22。(这种格式很有意义,因为它遵循业务逻辑 - 我正在按类别 id 加载报告数据,并返回几行。)

然而,

  • 当我使用 时find,js-data 会因可怕而死,[Error] "attrs" must be an object!因为它需要 1 行,否则无法被说服——除非我遗漏了一些东西。
  • 当我使用时findAll,我需要使用 uglier 进行搜索/report/?categoryId = 22- 并更改服务器
  • 当我使用动作时,它会将动作名称附加到我不需要的 URI 中,例如/report/22/myaction

有什么方法可以使用 find() 或 findAll()

  • 有一个干净的网址
  • 加载数据数组
  • 最好不要更改服务器实现
4

1 回答 1

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#finddoes GET /<resource>/:idDS#findAlldoes GET /<resource>

来自服务器的任何响应在到达时都需要采用正确的格式DS#inject

这些调用的生命周期如下:

  1. 适配器的 调用find或方法findAll
    1. GET适配器的调用方法
    2. HTTP适配器的调用方法
    3. deserialize服务器响应上的调用方法
  2. 将适配器响应传递给afterFindorafterFindAll钩子
  3. 查看cacheResponse
    1. 如果true,将afterFindor的结果传递afterFindAllDS#inject
    2. 如果false,将afterFindor的结果传递afterFindAllDS#createInstance
  4. 返回最终结果

避免注入错误的唯一方法是:

A) 不将适配器响应注入数据存储区

或者

B)在将数据传递到之前将数据按摩成正确的格式DS#inject

DS#inject需要具有由资源选项指定的字段的对象idAttribute或相同的数组。

您有三个机会在数据到达之前对其进行按摩DS#inject

  1. HTTP 响应拦截器
  2. deserialize钩子_
  3. afterFindafterFindAll钩_

在其中任何一种方法中,您都可以将数据修复为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#findDS#findAllRESTful 资源一起使用,其中 Resource 对应于数据库中的表,并且 Resource 的实例对应于表中的行。生成报告通常是您从不同来源编译数据、进行聚合等的事情之一。它不是可预测的(因此,这个问题)。

这是另一种选择:

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。如果您发现您编写的任何特定扩展或自定义都可以推广并让许多具有相同用例的其他人受益,请告诉我们

干杯!

于 2015-10-30T03:41:51.837 回答