tutorial ember data ember.js ember-data

data - ¿Cómo deben manejarse los errores cuando se usa el adaptador RESTA de Datos Ember.js?



ember tutorial (4)

Dado que actualmente no hay una buena solución en stock Ember-Data, hice mi propia solución agregando una propiedad apiErrors a DS.Model y luego en mi subclase RestAdapter (ya necesitaba la mía) createRecord callbacks de error a las llamadas Ajax para createRecord y updateRecord que guarda los errores y pone el modelo en el estado "inválido", que se supone que significa que las validaciones del lado del cliente o del lado del servidor fallaron.

Aquí están los fragmentos de código:

Esto puede ir en application.js o en algún otro archivo de nivel superior:

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

Esto va en las devoluciones de llamada de error para createRecord y updateRecord en una subclase 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''); }

ember-data.js: https://github.com/emberjs/data/tree/0396411e39df96c8506de3182c81414c1d0eb981

En resumen, cuando hay un error, quiero mostrar los mensajes de error en la vista, y luego el usuario puede 1) cancelar, lo que revertirá la transacción 2) corregir los errores de entrada y confirmar correctamente la transacción, pasando las validaciones en el servidor.

A continuación se muestra un fragmento de código de la fuente. No incluye una devolución de llamada de error.

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

En general, ¿cuál es el flujo de recibir un error del servidor y actualizar la vista? Parece que una devolución de llamada de error debería poner el modelo en un estado isError y luego la vista puede mostrar los mensajes apropiados. Además, la transacción debe mantenerse sucia. De esa forma, la transacción puede usar la rollback .

Parece que usar store.recordWasInvalid va en la dirección correcta, sin embargo.


Este fin de semana estaba tratando de descubrir lo mismo. Saliendo de lo que dijo Luke, eché un vistazo más de cerca a la fuente de datos de ascuas para la última confirmación (11 de diciembre).

TLDR; para manejar la actualización de datos de ember / crear errores, simplemente defina becameError() y becameInvalid(errors) en su instancia de DS.Model . La cascada activada por la devolución de llamada de error AJAX del RESTadapter eventualmente llamará a estas funciones que usted defina.

Ejemplo:

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}"

Aquí está el recorrido completo por la fuente:

En el adaptador REST, la función de error de devolución de llamada AJAX se da here :

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 se define here y, a su vez, llama al registroWasInvalid o recordWasError de la tienda según la respuesta:

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

A su vez, store.recordWasInvalid y store.recordWasError (definidos here ) llaman a los manejadores de registro (un modelo de DS). En el caso no válido, pasa mensajes de error del adaptador como argumento.

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

DS.Model.adapterDidInvalidate y adapterDidError (definidos here ) simplemente send(''becameInvalid'', errors) o send(''becameError'') que finalmente nos lleva a los manejadores here :

didLoad: Ember.K, didUpdate: Ember.K, didCreate: Ember.K, didDelete: Ember.K, becameInvalid: Ember.K, becameError: Ember.K,

(Ember.K es solo una función ficticia para devolver this . Consulte here )

Entonces, la conclusión es que simplemente necesita definir funciones para becameInvalid y becameError en su modelo para manejar estos casos.

Espero que esto ayude a alguien más; los documentos ciertamente no reflejan esto en este momento.


Me encontré con una situación así, no estoy seguro si esto ya se explica en alguna parte.

Estoy usando:

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

El modelo se mezcló inicialmente con Validación 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'') } } } });

En la plantilla, se agrega el manillar correspondiente. (tenga en cuenta que las validaciones de model.errors.<attribute> agregarán automáticamente errores a model.errors.<attribute> en caso de validaciones de entrada, también model.errors.<attribute> misma compensación en las validaciones del servidor)

<p>{{t ''translations.myString''}}<br> {{view Ember.TextField valueBinding="attributeName"}} {{#if model.errors.attributeName.length}}<small class="error">{{model.errors.attributeName}}</small>{{/if}} </p

Ahora, guardaremos la 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 });

Ahora, si se produce un error de validación desde el servidor, el paquete devuelto que se utiliza es

{"errors":{"attributeName1":"translations.attributeNameEror", "another":"translations.anotherError"}} status : 422

Es importante usar el estado 422

De esta forma, sus atributos pueden validarse en el lado del cliente y nuevamente en el lado del servidor.

Descargo de responsabilidad: ¡No estoy seguro si esta es la mejor manera!


DS.RESTAdapter acaba de obtener un poco más de manejo de errores en este compromiso, pero todavía no estamos en un punto en el que tengamos una gran recomendación para el manejo de errores.

Si eres lo suficientemente ambicioso / loco como para poner aplicaciones en producción hoy con datos de ascuas (¡como he estado!), Lo mejor es asegurarte de que la probabilidad de fallas en tu API sea extremadamente baja. es decir, validar su información del lado del cliente.

Con suerte, podemos actualizar esta pregunta con una respuesta mucho mejor en los próximos meses.