Как следует обращаться с ошибками при использовании 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
идет в правильном направлении.
Ответы
Ответ 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');
}