42

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朝着正确的方向发展。

4

4 回答 4

42

这个周末我试图弄清楚同样的事情。根据 Luke 所说的,我仔细查看了最新提交(12 月 11 日)的 ember-data 源。

TLDR;要处理 ember-data 更新/创建错误,只需在您的实例上定义becameError()和。RESTadapter 的 AJAX 错误回调触发的级联最终会调用你定义的这些函数。becameInvalid(errors)DS.Model

例子:

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 回调错误函数:

   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在此处定义)调用记录(DS.Model)的处理程序。在无效的情况下,它会将来自适配器的错误消息作为参数传递。

 recordWasInvalid: function(record, errors) {
    record.adapterDidInvalidate(errors);
  },

  recordWasError: function(record) {
    record.adapterDidError();
  },

DS.Model.adapterDidInvalidateadapterDidError在这里定义)简单地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。见这里

因此,结论是,您只需为模型定义函数becameInvalidbecameError在模型上定义函数来处理这些情况。

希望这对其他人有所帮助;文档现在当然没有反映这一点。

于 2012-12-12T17:30:58.553 回答
8

DS.RESTAdapter刚刚在这个提交中得到了更多的错误处理,但我们还没有到我们对错误处理有很好的建议的地步。

如果您有足够的野心/疯狂到今天使用 ember-data 将应用程序投入生产(就像我一样!),最好确保您的 API 失败的可能性极低。即验证您的数据客户端。

希望我们能在接下来的几个月里用更好的答案更新这个问题。

于 2012-11-23T05:10:09.317 回答
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')
        }
    }
}
});

在模板中,添加了相应的车把。(请注意,model.errors.<attribute>在输入验证的情况下,ember 验证会自动添加错误,我也会在服务器验证中使用相同的权衡)

<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很重要

因此,通过这种方式,您的属性可以在客户端和服务器端再次验证。

免责声明:我不确定这是否是最好的方法!

于 2014-02-27T10:27:10.383 回答
2

由于库存 Ember-Data 目前没有好的解决方案,我通过向apiErrorsDS.Model 添加一个属性然后在我的 RestAdapter 子类(我已经需要我自己的)中添加了错误回调到 Ajax 调用createRecordupdateRecord保存错误并将模型置于“无效”状态,这应该意味着客户端或服务器端验证失败。

这是代码片段:

这可以放在 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');
}
于 2012-12-04T18:04:22.917 回答