使用Ember Data JSON-API适配器(现在是默认值)处理错误

iswrvxsc  于 2022-12-26  发布在  其他
关注(0)|答案(1)|浏览(147)

我使用的是Ember 1.13.7和Ember Data 1.13.8,它们默认使用JSON-API标准来格式化发送到API和从API接收的有效负载。
我想使用Ember数据的内置错误处理,以显示红色的“错误”表单字段给用户。我已经格式化了我的API错误响应按照JSON-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”对象:
source:包含对错误源的引用的对象,可以选择包括以下任一成员:
指针:指向请求文档中关联实体的JSON指针[RFC 6901][例如,“/data”表示主要数据对象,或“/data/attributes/title”表示特定属性]。
parameter:指示哪个查询参数导致错误的字符串。
但这是我应该做的,以便告诉ember数据哪些字段,它应该标记为处于错误状态?
如果有人能帮我解释一下,我将不胜感激。
谢谢。

f45qwnt8

f45qwnt81#

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

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)处理错误的方式都有一点不同。
In your case you want to handle validation errors for your form which probably means validation errors. The format for errors as specified by the JSON API can be found here: http://jsonapi.org/format/#error-objects
您会注意到,API只指定在以errors为键的顶级数组中返回错误,所有其他错误属性都是可选的。

{
    "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数据将返回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。在这两种情况下,都将调用承诺的拒绝处理程序。

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"
    }
]

基本上detailMap到messagesource/pointerMap到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,并确保errors属性存在,如果存在,则创建一个新的DS.InvalidError并将其返回,这将导致与默认行为相同的行为,默认行为期望422 HTTP状态代码(例如,您的JSON API错误将被处理,消息将被放入模型上的错误散列中)。

相关问题