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

时间:2015-08-10 11:38:31

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

我使用的是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中查看,我可以看到模型" s" isError" value设置为true但是我无法看到Ember Data如何知道模型中哪个字段是错误状态的字段?我从官方的JSON-API页面(http://jsonapi.org/format/#errors)中看到,您可以包含一个"来源"错误响应中的对象:

  

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

     
    

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

         

参数:表示哪个查询的字符串     参数导致错误。

  

但这是我应该做的,以便告诉Ember Data它应该标记哪些字段处于错误状态?

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

感谢。

1 个答案:

答案 0 :(得分:86)

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

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属性和{{1} }属性。 source/pointer属性被设置为错误消息,detail属性允许Ember Data确定模型中的哪个属性导致问题。因此,Ember Data要求的有效JSON API错误对象(如果您正在使用现在默认的JSONAPI)是这样的:

source/pointer

请注意{ "errors": [ { "detail": "The attribute `is-admin` is required", "source": { "pointer": "data/attributes/is-admin" } } ] } 不是复数(对我来说是一个常见的错误),detail的值不应包含前导斜杠,属性名称应该是dasherized。

最后,您必须使用HTTP代码source/pointer返回验证错误,这意味着" Unprocessable Entity"。如果您未返回422代码,则默认情况下,Ember Data将返回422,并且不会在模型的AdapterError哈希上设置错误消息。这让我有点困难,因为我使用HTTP代码errors(错误请求)将验证错误返回给客户端。

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

true

默认情况下,如果返回的HTTP代码是model.save().then(function(){ // yay! it worked }, function(){ // it failed for some reason possibly a Bad Request (400) // possibly a validation error (422) } 并且您具有正确的JSON API错误格式,那么您可以通过访问模型的错误哈希来访问错误消息,其中哈希键是您的属性名。哈希以camelcase格式键入属性名称。

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

is-admin

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

model.get('errors.isAdmin');

基本上[ { "attribute": "isAdmin", "message": "The attribute `is-admin` is required" } ] 映射到detailmessage映射到source/pointer。如果您在单个属性上有多个验证错误,则返回一个数组(JSON API允许您返回多个验证错误,而不是仅返回第一个验证失败)。您可以直接在模板中使用错误值,如下所示:

attribute

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

如果您的API不使用HTTP {{#each model.errors.isAdmin as |error|}} <div class="error"> {{error.message}} </div> {{/each}} 代码进行验证错误(例如,如果它使用422),那么您可以通过覆盖400来更改JSONAPIAdapter的默认行为自定义适配器中的方法。下面是一个示例,它为handleResponse的任何HTTP响应状态代码返回一个新的InvalidError对象。

400

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

希望有所帮助!