Как следует обрабатывать ошибки при использовании RESTAdapter данных Ember.js?

Эмбер-data.js:https://github.com/emberjs/data/tr,ee/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 все же идет в правильном направлении.

 sly7_719 окт. 2012 г., 11:12
Существует еще не полный механизм для обработки ошибок, см.github.com/emberjs/data/pull/376Возможно, вы найдете то, что хотите.
 Mars20 окт. 2012 г., 04:45
Да, отсутствие обработки ошибок удивительно, но приятно, что нет обработки ошибок, в отличие от наивной реализации, которая изменится позже. Я написал свое недавнее приложение Ember, чтобы избежать ошибок сервера, выполнив некоторые проверки на стороне клиента, прежде чем делатьApp.store.commit().

Ответы на вопрос(4)

DS.RESTAdapter только что получил немного больше ошибок в обработкеэтот коммит но мы еще не дошли до того момента, когда у нас будет отличная рекомендация по обработке ошибок.

Если вы достаточно амбициозны / сумасшедшие, чтобы сегодня запускать приложения с ember-данными (как я это делал!), То лучше всего убедиться, что вероятность сбоев в вашем API чрезвычайно низка. то есть проверить ваши данные на стороне клиента.

Надеюсь, мы сможем обновить этот вопрос с гораздо лучшим ответом в ближайшие месяцы.

 Vladislav Rastrusny06 мая 2015 г., 11:56
Каково состояние обработки ошибок в Ember.Data сегодня?

я создал собственное решение, добавивapiErrors Свойство для DS.Model, а затем в моем подклассе RestAdapter (я уже нуждался в своем собственном), я добавил обратные вызовы ошибок в вызовах Ajax дляcreateRecord а такжеupdateRecord это сохраняет ошибки и переводит модель в «недопустимое» состояние, что должно означать сбой проверки на стороне клиента или на стороне сервера.

Вот фрагменты кода:

Это можно сделать в application.js или в другом файле верхнего уровня:

DS.Model.reopen({
  // Added for better error handling on create/update
  apiErrors: null
});

Это идет в обратном вызове ошибки дляcreateRecord а такжеupdateRecord в подклассе RestAdapter:

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');
}

не уверенный, объяснил ли это где-нибудь уже.

Я использую:

Em.VERSION : 1.0.0
DS.VERSION : "1.0.0-beta.6"
Ember Validations (dockyard) : Version: 1.0.0.beta.1
Ember I18n

Модель была изначально смешана с миксином Validation.

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

Таким образом, ваши атрибуты могут быть проверены на стороне клиента и снова на стороне сервера.

Отказ от ответственности: я не уверен, что это лучший способ!

что сказал Люк, я поближе рассмотрел источник данных ember дляпоследний коммит (11 декабря).

TLDR; для обработки ошибок обновления / создания данных ember, просто определитеbecameError() а такжеbecameInvalid(errors) на вашеDS.Model экземпляр. Каскад, вызванный обратным вызовом ошибки AJAX RESTadapter, в конечном итоге вызовет эти функции, которые вы определили.

Пример:

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 определенВот и это в свою очередь вызывает storeWasInvalid или 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.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 на вашей модели, чтобы справиться с этими случаями.

Надеюсь, это поможет кому-то еще; документы конечно не отражают это прямо сейчас.

 Nick Ragaz23 янв. 2013 г., 21:05
Вы также можете использовать одноразовый обратный вызов, добавивmodel.one('becameInvalid', function() { // error handling here }) перед фиксацией транзакции, если вы хотите обрабатывать ошибки по-разному в зависимости от контекста.
 incognick29 апр. 2013 г., 02:37
Отличное объяснение! Спасибо.
 genkilabs05 дек. 2013 г., 21:14
STALE: проверка состояния 422, кажется, была перемещена в active_model_adapter:github.com/emberjs/data/blob/...
 dineth20 авг. 2013 г., 03:54
Отличное объяснение здесь. Единственное, что не рассматривается, - это как распространить ошибку на модель, чтобы событие ошибки Ember.Route могло действовать соответствующим образом. Пользователь может перейти к идентификатору, который не существует, и в этом случае вы хотите дать ему правильную ошибку. Таким образом, сочетание этого и ответа выше может иметь смысл.
 RyanJM25 апр. 2013 г., 21:53
Кажется, это не работает для уничтожения. Это правильно?

Ваш ответ на вопрос