使用 Ember.js 数据 RESTAdapter 时应该如何处理错误?
Posted
技术标签:
【中文标题】使用 Ember.js 数据 RESTAdapter 时应该如何处理错误?【英文标题】:How should errors be handled when using the Ember.js Data RESTAdapter? 【发布时间】:2012-10-09 17:57:16 【问题描述】:ember-data.js:https://github.com/emberjs/data/tree/0396411e39df96c8506de3182c81414c1d0eb981
简而言之,当出现错误时,我想在视图中显示错误信息,然后用户可以 1)取消,这将回滚事务 2)更正输入错误并成功提交事务,通过服务器上的验证。
下面是来自源代码的代码 sn-p。它不包含错误回调。
updateRecord: function(store, type, record)
var id = get(record, 'id');
var root = this.rootForType(type);
var data = ;
data[root] = this.toJSON(record);
this.ajax(this.buildURL(root, id), "PUT",
data: data,
context: this,
success: function(json)
this.didUpdateRecord(store, type, record, json);
);
,
总的来说,从服务器接收错误并更新视图的流程是什么?似乎错误回调应该将模型置于isError
状态,然后视图可以显示适当的消息。此外,交易应该保持肮脏。这样,交易就可以使用rollback
。
不过,使用store.recordWasInvalid
似乎是朝着正确的方向发展。
【问题讨论】:
目前还没有完善的错误处理机制,请看github.com/emberjs/data/pull/376,或许你会找到你想要的。 是的,缺少错误处理令人惊讶,但是没有错误处理,而不是稍后会更改的幼稚实现,这很好。我已经编写了我最近的 Ember 应用程序,通过在客户端执行一些验证来避免服务器错误,然后再执行App.store.commit()
。
【参考方案1】:
这个周末我试图弄清楚同样的事情。根据 Luke 所说的,我仔细查看了 latest commit(12 月 11 日)的 ember 数据源。
TLDR;要处理 ember-data 更新/创建错误,只需在您的 DS.Model
实例上定义 becameError()
和 becameInvalid(errors)
。 RESTadapter的AJAX错误回调触发的级联最终会调用你定义的这些函数。
例子:
App.Post = DS.Model.extend
title: DS.attr "string"
body: DS.attr "string"
becameError: ->
# handle error case here
alert 'there was an error!'
becameInvalid: (errors) ->
# record was invalid
alert "Record was invalid because: #errors"
这里是完整的源代码:
在REST适配器中,AJAX回调错误函数被赋予here:
this.ajax(this.buildURL(root, id), "PUT",
data: data,
context: this,
success: function(json)
Ember.run(this, function()
this.didUpdateRecord(store, type, record, json);
);
,
error: function(xhr)
this.didError(store, type, record, xhr);
);
didError 被定义为here 并根据响应依次调用商店的recordWasInvalid 或recordWasError:
didError: function(store, type, record, xhr)
if (xhr.status === 422)
var data = JSON.parse(xhr.responseText);
store.recordWasInvalid(record, data['errors']);
else
store.recordWasError(record);
,
反过来,store.recordWasInvalid
和 store.recordWasError
(定义为 here)调用记录(DS.Model)的处理程序。在无效的情况下,它会将来自适配器的错误消息作为参数传递。
recordWasInvalid: function(record, errors)
record.adapterDidInvalidate(errors);
,
recordWasError: function(record)
record.adapterDidError();
,
DS.Model.adapterDidInvalidate
和 adapterDidError
(定义为 here)只是 send('becameInvalid', errors)
或 send('becameError')
最终将我们引向处理程序 here:
didLoad: Ember.K,
didUpdate: Ember.K,
didCreate: Ember.K,
didDelete: Ember.K,
becameInvalid: Ember.K,
becameError: Ember.K,
(Ember.K 只是一个用于返回this
的虚拟函数。参见here)
因此,结论是,您只需在模型上为 becameInvalid
和 becameError
定义函数即可处理这些情况。
希望这对其他人有所帮助;文档现在肯定没有反映这一点。
【讨论】:
如果您想根据上下文以不同方式处理错误,您还可以通过在提交事务之前添加model.one('becameInvalid', function() // error handling here )
来使用一次性回调。
很好的解释!非常感谢。
这里有很好的解释。唯一没有涉及的是如何将错误传播到模型,以便 Ember.Route 的错误事件可以相应地采取行动。用户可能导航到了一个不存在的 ID,在这种情况下,您希望为他们提供正确的错误。所以把这个和上面的答案结合起来可能是有意义的。
STALE:对 422 状态的检查似乎已移至 active_model_adapter:github.com/emberjs/data/blob/…
从服务器检索到的 json 哈希必须有 "errors" 键,其中包含错误。否则会引发错误。【参考方案2】:
DS.RESTAdapter
刚刚在 this commit 中获得了更多的错误处理,但我们还没有达到对错误处理提出很好建议的地步。
如果您现在有足够的野心/疯狂地使用 ember-data 将应用程序投入生产(就像我一样!),最好确保您的 API 发生故障的可能性极低。即在客户端验证您的数据。
希望我们能在接下来的几个月里用更好的答案更新这个问题。
【讨论】:
Ember.Data 今天的错误处理状态如何?【参考方案3】:我刚遇到这种情况,不确定是否已经在任何地方解释过。
我正在使用:
Em.VERSION : 1.0.0
DS.VERSION : "1.0.0-beta.6"
Ember Validations (dockyard) : Version: 1.0.0.beta.1
Ember I18n
该模型最初是与 Validation mixin 混合的。
App.Order = DS.Model.extend(Ember.Validations.Mixin,
.....
someAttribute : DS.attr('string'),
/* Client side input validation with ember-validations */
validations :
someAttribute :
presence :
message : Ember.I18n.t('translations.someAttributeInputError')
);
在模板中,添加了相应的车把。 (请注意,在输入验证的情况下,ember 验证会自动将错误添加到 model.errors.<attribute>
,我也会在服务器验证中使用相同的权衡)
<p>t 'translations.myString'<br>
view Ember.TextField valueBinding="attributeName"
#if model.errors.attributeName.length<small class="error">model.errors.attributeName</small>/if
</p
现在,我们将保存Order
App.get('order').save().then(function ()
//move to next state?
, function(xhr)
var errors = xhr.responseJSON.errors;
for(var error in errors) //this loop is for I18n
errors[error] = Ember.I18n.t(errors[error]);
controller.get('model').set('errors', errors); //this will overwrite current errors if any
);
现在如果服务器抛出一些验证错误,返回的数据包是
"errors":"attributeName1":"translations.attributeNameEror",
"another":"translations.anotherError"
status : 422
使用状态422
很重要这样,您的属性可以在客户端和服务器端再次验证。
免责声明:我不确定这是否是最好的方法!
【讨论】:
【参考方案4】:由于目前在 Ember-Data 中没有好的解决方案,我通过向 DS.Model 添加 apiErrors
属性,然后在我的 RestAdapter 子类(我已经需要我自己的)中添加了错误回调来创建自己的解决方案Ajax 调用 createRecord
和 updateRecord
保存错误并将模型置于“无效”状态,这应该意味着客户端或服务器端验证失败。
这里是sn-ps的代码:
这可以放在 application.js 或其他一些***文件中:
DS.Model.reopen(
// Added for better error handling on create/update
apiErrors: null
);
这会出现在 RestAdapter 子类中 createRecord
和 updateRecord
的错误回调中:
error: function(xhr, textStatus, err)
console.log(xhr.responseText);
errors = null;
try
errors = JSON.parse(xhr.responseText).errors;
catch(e) //ignore parse error
if(errors)
record.set('apiErrors',errors);
record.send('becameInvalid');
【讨论】:
以上是关于使用 Ember.js 数据 RESTAdapter 时应该如何处理错误?的主要内容,如果未能解决你的问题,请参考以下文章