【问题标题】:Handling errors with the (now default) Ember Data JSON-API adapter使用(现在默认的)Ember Data JSON-API 适配器处理错误
【发布时间】:2015-11-02 07:24:49
【问题描述】:

我使用的是 Ember 1.13.7 和 Ember Data 1.13.8,它们默认使用 JSON-API 标准来格式化发送到 API 和从 API 接收的负载。

我想使用 Ember Data 的内置错误处理来向用户显示红色的“错误”表单字段。我已经按照 JSON-API 标准格式化了我的 API 错误响应,例如

{"errors":[
    {
        "title":"The included.1.attributes.street name field is required.", 
        "code":"API_ERR", 
        "status":"400", 
    }
]}

当我尝试保存我的模型时,错误回调正在正确执行。如果我在 Ember Inspector 中查看,我可以看到模型的“isError”值设置为 true,但我看不到 Ember Data 应该如何知道模型中的哪个字段处于错误状态?我从官方 JSON-API 页面 (http://jsonapi.org/format/#errors) 中看到,您可以在错误响应中包含“源”对象:

source:一个包含对错误源的引用的对象, 可选地包括以下任何成员:

pointer:指向请求文档中关联实体的 JSON 指针 [RFC6901] [例如。 “/data”表示主要数据对象,或“/data/attributes/title” 对于特定属性]。

参数:一个字符串,指示哪个查询 参数导致错误。

但是为了告诉 Ember Data 它应该将哪些字段标记为处于错误状态,我应该这样做吗?

如果有人能帮助阐明这一点,我将不胜感激。

谢谢。

【问题讨论】:

  • 我仍然遇到错误和新的 JSON API 格式的问题,但根据此页面,您应该提供与错误的属性名称匹配的 source/pointer 属性。 emberjs.com/api/data/classes/DS.InvalidError.html
  • 是的,我上周发现了,但我还没有机会尝试。不过感谢您的回复。
  • 没问题,如果你设法让它全部工作,请更新你的问题。我相信这对很多人会有帮助。 (我知道这对我有帮助哈哈!)
  • 是的,没问题。

标签: ember.js ember-data ember-cli json-api


【解决方案1】:

请注意,以下答案基于以下版本:

DEBUG: -------------------------------
ember.debug.js:5442DEBUG: Ember                     : 1.13.8
ember.debug.js:5442DEBUG: Ember Data                : 1.13.9
ember.debug.js:5442DEBUG: jQuery                    : 1.11.3
DEBUG: -------------------------------

不幸的是,错误处理文档目前分散在各处,因为您处理不同适配器(Active、REST、JSON)的错误的方式都有些不同。

在您的情况下,您想要处理表单的验证错误,这可能意味着验证错误。 JSON API 指定的错误格式可以在这里找到:http://jsonapi.org/format/#error-objects

您会注意到 API 仅指定在由 errors 键入的顶级数组中返回错误,并且所有其他错误属性都是可选的。因此,似乎 JSON API 所需的一切如下:

{
    "errors": [
     {}
    ]
}  

当然,要让 Ember Data 和 JSONAPIAdapter 开箱即用地处理错误,您至少需要包含 detail 属性和 source/pointer 属性。 detail 属性被设置为错误消息,source/pointer 属性让 Ember Data 找出模型中的哪个属性导致了问题。因此,Ember Data 要求的有效 JSON API 错误对象(如果您使用的是现在默认的 JSONAPI)是这样的:

{
    "errors": [
     {
        "detail": "The attribute `is-admin` is required",
        "source": {
             "pointer": "data/attributes/is-admin"
         }
     }
    ]
}  

请注意,detail 不是复数(对我来说是一个常见错误),source/pointer 的值不应包含前导正斜杠,并且属性名称应虚化。

最后,您必须使用 HTTP 代码 422 返回您的验证错误,这意味着“无法处理的实体”。如果您不返回 422 代码,则默认情况下 Ember Data 将返回 AdapterError 并且不会在模型的 errors 哈希上设置错误消息。这让我有点苦恼,因为我使用 HTTP 代码400(错误请求)向客户端返回验证错误。

ember 数据区分这两种错误的方式是验证错误返回一个 InvalidError 对象 (http://emberjs.com/api/data/classes/DS.InvalidError.html)。这将导致模型上的 errors 哈希被设置,但不会将 isError 标志设置为 true(不知道为什么会这样,但在此处记录:http://emberjs.com/api/data/classes/DS.Model.html#property_isError)。默认情况下,422 以外的 HTTP 错误代码将导致返回 AdapterError 并将 isError 标志设置为 true。在这两种情况下,promise 的拒绝处理程序都会被调用。

model.save().then(function(){
    // yay! it worked
}, function(){
    // it failed for some reason possibly a Bad Request (400)
    // possibly a validation error (422)
}

默认情况下,如果返回的 HTTP 代码是 422 并且您具有正确的 JSON API 错误格式,那么您可以通过访问模型的错误哈希来访问错误消息,其中哈希键是您的属性名称。哈希以驼峰格式键入属性名称。

例如,在我们上面的 json-api 错误示例中,如果 is-admin 出现错误,您将像这样访问该错误:

model.get('errors.isAdmin');

这将返回一个包含错误对象的数组,格式如下:

[
   {
      "attribute": "isAdmin",
      "message": "The attribute `is-admin` is required"
    }
]

基本上detail 映射到messagesource/pointer 映射到attribute。如果您在单个属性上有多个验证错误,则会返回一个数组(JSON API 允许您返回多个验证错误,而不是只返回第一个失败的验证)。您可以像这样在模板中直接使用错误值:

{{#each model.errors.isAdmin as |error|}}
    <div class="error">
      {{error.message}}
    </div>
{{/each}}

如果没有错误,那么上面的内容将不会显示任何内容,因此它可以很好地处理表单验证消息。

如果您的 API 不使用 HTTP 422 代码来验证错误(例如,如果它使用 400),那么您可以通过覆盖自定义适配器中的 handleResponse 方法来更改 JSONAPIAdapter 的默认行为。下面是一个示例,它为任何 HTTP 响应状态代码(400)返回一个新的 InvalidError 对象。

import DS from "ember-data";
import Ember from "ember";

export default DS.JSONAPIAdapter.extend({
  handleResponse: function(status, headers, payload){
    if(status === 400 && payload.errors){
      return new DS.InvalidError(payload.errors);
    }
    return this._super(...arguments);
  }
});

在上面的示例中,我正在检查 HTTP 状态是否为 400 并确保存在错误属性。如果是这样,那么我创建一个新的DS.InvalidError 并返回它。这将导致与预期 422 HTTP 状态代码的默认行为相同的行为(即,将处理您的 JSON API 错误并将消息放入模型上的错误哈希中)。

希望有帮助!

【讨论】:

  • 好的,相关模型中的属性错误现在是我的问题。我可以通过执行 model.errors.content 或 model.errors.messages 查看这些相关模型上的错误,但如果我想检查相关模型上的特定属性以突出显示字段错误,我会得到 null 或 undefined 值。跨度>
  • 您能否提出另一个问题,详细说明您的模型是如何设置的、如何保存模型以及您要发回什么响应?我还没有尝试过使用关系,所以无法在我自己的项目中轻松尝试。
  • 您可能不需要重写 handleResponse 方法...相反,您可以简单地重新定义 isInvalid 方法来查找 400 状态以及默认的 422。请参见此处:@ 987654324@
  • 我希望我能多次投票。非常感谢!
  • 这个 SO 答案在编写 8 个月后仍然是关于使用默认适配器在 Ember.js 路由中进行错误处理的最长、最简洁的文档。
猜你喜欢
  • 2016-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多