Подтвердить что ты не робот

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

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 идет в правильном направлении.

4b9b3361

Ответ 1

В эти выходные я пытался понять то же самое. Исходя из того, что сказал Люк, я более подробно рассмотрел источник данных ember-data для последней фиксации (11 декабря).

TL;DR; для обработки ошибок ember-data/create errors просто определите 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 предоставляется здесь:

   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 для вашей модели для обработки этих случаев.

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

Ответ 2

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

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

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

Ответ 3

Я просто столкнулся с такой ситуацией, не уверен, что это уже объяснено где угодно.

Я использую:

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

Сначала модель была смешана с валидацией.

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, я сделал свое собственное решение, добавив свойство 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');
}