ember-data.js:https://github.com/emberjs/data/tree/0396411e39df96c8506de3182c81414c1d0eb981
简而言之,当出现错误时,我想在视图中显示错误消息,然后用户可以1)取消,这将回滚事务2)纠正输入错误并成功提交事务,通过服务器上的验证。
以下是来自源代码的代码段。它不包含错误回调。
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
正朝着正确的方向发展。
答案 0 :(得分:42)
本周末,我试图想出同样的事情。关闭卢克所说的,我仔细研究了latest commit(12月11日)的余烬数据来源。
<强> TLDR;要处理余烬数据更新/创建错误,只需在becameError()
实例上定义becameInvalid(errors)
和DS.Model
即可。由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
的函数来处理这些情况。
希望这有助于其他人;文档当然没有反映这一点。
答案 1 :(得分:8)
DS.RESTAdapter
在this commit中进行了更多的错误处理,但我们还没有达到我们对错误处理的强烈建议。
如果你雄心勃勃/疯狂到今天使用ember-data将应用程序投入生产(就像我一直这样!),最好确保你的API失败的可能性非常低。即验证您的数据客户端。
希望我们能在未来几个月内以更好的答案更新这个问题。
答案 2 :(得分: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
非常重要因此,您的属性可以在客户端验证,也可以在服务器端验证。
免责声明:我不确定这是否是最佳方式!
答案 3 :(得分:2)
由于Ember-Data目前没有很好的解决方案,我通过向DS.Model添加apiErrors
属性然后在我的RestAdapter子类(我已经需要自己的)中创建了自己的解决方案。我添加了错误回调Ajax调用createRecord
和updateRecord
来保存错误并将模型置于“无效”状态,这应该意味着客户端或服务器端验证失败。
以下是代码段:
这可以放在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');
}