在使用Ember.js数据RESTAdapter时应如何处理错误?
ember-data.js: https : //github.com/emberjs/data/tree/0396411e39df96c8506de3182c81414c1d0eb981
总之,当出现错误时,我想在视图中显示错误消息,然后用户可以1)取消,这将回滚事务2)纠正input错误并成功提交事务,通过validation服务器。
以下是源代码片段。 它不包含错误callback。
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); } }); },
总体而言,从服务器接收错误并更新视图的stream程是什么? 看起来,错误callback应该把模型置于isError
状态,然后视图可以显示相应的消息。 此外,交易应该保持肮脏。 这样,事务可以使用rollback
。
看来,使用store.recordWasInvalid
是朝着正确的方向,虽然。
这个周末我正在试图找出同样的事情。 走出卢克所说的,我仔细看了一下最新的提交 (12月11日)的烬数据源。
TLDR; 要处理ember-data更新/创build错误,只需在您的DS.Model
实例上定义becameError()
和becameInvalid(errors)
DS.Model
。 由RESTadapter的AJAX错误callback触发的级联最终将调用您定义的这些函数。
例:
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适配器中,AJAXcallback错误函数在这里给出:
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是在这里定义的,它依次调用存储的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
( 在这里定义)调用logging(DS.Model)的处理程序。 在无效的情况下,它将来自适配器的错误消息作为parameter passing。
recordWasInvalid: function(record, errors) { record.adapterDidInvalidate(errors); }, recordWasError: function(record) { record.adapterDidError(); },
DS.Model.adapterDidInvalidate
和adapterDidError
(定义在这里 )只是send('becameInvalid', errors)
或send('becameError')
,最终引导我们到这里的处理程序:
didLoad: Ember.K, didUpdate: Ember.K, didCreate: Ember.K, didDelete: Ember.K, becameInvalid: Ember.K, becameError: Ember.K,
(Ember.K只是一个虚拟的函数来返回this
。
所以,结论是,你只需要在你的模型中定义函数becameInvalid
和becameError
来处理这些情况。
希望这可以帮助别人; 该文件当然不反映这个权利。
DS.RESTAdapter
在这个提交中只是得到了更多的error handling,但是我们仍然没有很好地推荐error handling。
如果你有足够的野心/疯狂地把应用程序放在今天的产品中(像我一样!),最好确保你的API失败的可能性非常低。 即validation你的数据客户端。
希望在接下来的几个月里能更好地回答这个问题。
我只是遇到了这样的情况,不知道这是否已经在任何地方解释。
我在用:
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') } } } });
在模板中,添加相应的句柄。 (注意,在inputvalidation的情况下,embervalidation会自动将错误添加到model.errors.<attribute>
中,我也将在服务器validation中使用相同的权衡)
<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 });
现在,如果从服务器抛出一些validation错误,正在使用的返回的数据包是
{"errors":{"attributeName1":"translations.attributeNameEror", "another":"translations.anotherError"}} status : 422
使用状态422很重要
所以这样,你的属性可以在客户端和服务器端validation。
免责声明:我不确定这是否是最好的方法!
由于目前股票Ember-Data没有很好的解决scheme,我通过向apiErrors
添加apiErrors
属性,然后在RestAdapter子类(我已经需要我自己的)中创build了自己的解决scheme,并向Ajax调用createRecord
添加了错误callback函数, updateRecord
保存错误并将模型置于“无效”状态,这意味着客户端或服务器端validation失败。
以下是代码片段:
这可以在application.js或其他一些顶级文件中进行:
DS.Model.reopen({ // Added for better error handling on create/update apiErrors: null });
这在RestAdapter子类中的createRecord
和updateRecord
的错误callback中进行:
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'); }