42 votes

Comment les erreurs doivent-elles être traitées lors de l'utilisation de Data RESTAdapter Ember.js?

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

En bref, quand il ya une erreur, je veux afficher les messages d'erreur dans la vue, puis l'utilisateur peut 1) de les annuler, ce qui annulera la transaction 2) corriger les erreurs de saisie et de réussir à valider la transaction, en passant les validations sur le serveur.

Ci-dessous est un extrait de code à partir de la source. Il ne comprend pas une erreur de rappel.

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

Dans l'ensemble, quel est le flux de la réception d'une erreur de la part du serveur et la mise à jour de la vue? Il semble qu'une erreur de rappel devrait mettre le modèle dans un isError de l'état, et alors que la vue peut afficher les messages appropriés. Aussi, la transaction devrait rester sale. De cette manière, la transaction peut utiliser rollback.

Il semble que l'utilisation d' store.recordWasInvalid va dans la bonne direction, bien.

42voto

Sherwin Yu Points 1755

Ce week-end j'ai été à essayer de comprendre la même chose. Aller au large de ce que Luc dit, j'ai pris un peu plus près à la braise de source de données pour le dernier commit (11 Déc.).

TLDR; à la poignée de braise-mise à jour des données/créer des erreurs, il suffit de définir becameError() et becameInvalid(errors) sur votre DS.Model de l'instance. La cascade déclenchés par la RESTadapter de l'AJAX d'erreur de rappel finira par appeler ces fonctions que vous définissez.

Exemple:

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

Voici la pleine promenade à travers la source:

Dans le RESTE de l'adaptateur, l'AJAX rappel de la fonction d'erreur est donnée ici:

   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 est défini ici, et il appelle à son tour du magasin recordWasInvalid ou recordWasError en fonction de la réponse:

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

À son tour, store.recordWasInvalid et store.recordWasError (défini ici), appeler le dossier (DS.Modèle)'s des gestionnaires. Dans l'invalide cas, il transmet des messages d'erreur à partir de la carte comme un argument.

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

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

DS.Model.adapterDidInvalidate et adapterDidError (défini ici), il suffit d' send('becameInvalid', errors) ou send('becameError') qui finalement nous conduit aux gestionnaires d' ici:

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

(De braise.K est juste un mannequin fonction pour renvoyer this. Voir ici)

Donc, la conclusion est, vous avez simplement besoin de définir des fonctions pour becameInvalid et becameError sur votre modèle pour gérer ces cas.

Espérons que cela aide quelqu'un d'autre; les documents ne reflètent pas ce droit maintenant.

8voto

Luke Melia Points 5887

DS.RESTAdapter juste obtenu un peu plus de la gestion des erreurs dans ce commit , mais nous sommes pas encore à un point où nous avons une grande recommandation pour le traitement des erreurs.

Si vous êtes ambitieux/assez fou pour mettre des applications en production aujourd'hui avec ember-data (comme je l'ai été!), il est préférable de s'assurer que la probabilité de défaillances dans votre API est extrêmement faible. c'est à dire valider vos données côté client.

J'espère que nous pourrons mettre à jour cette question avec une bien meilleure réponse dans les mois à venir.

3voto

sabithpocker Points 5021

J'ai juste couru dans une telle situation, vous ne savez pas si cela est déjà expliqué, n'importe où.

Je suis à l'aide de:

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

Le modèle a d'abord été mixedin avec la 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')
        }
    }
}
});

Dans le modèle, correspondant guidon est ajouté. (notez que la braise validations ajoutera automatiquement les erreurs d' model.errors.<attribute> dans le cas de validations d'entrée, je vais être en utilisant le même compromis dans le serveur de validations ainsi)

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

Maintenant, nous allons économiser de l' 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
});

Maintenant, si il ya une erreur de validation levée à partir du serveur, le retour de paquet utilisé est

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

status : 422

Il est important d'utiliser le statut de 422

Ainsi, de cette façon, votre attribut(s) peut être validée côté client et côté serveur.

Disclaimer : je ne suis pas sûr si c'est le meilleur moyen!

2voto

webjprgm Points 1136

Car il n'y a actuellement pas de bonne solution en stock Ember-Data, j'ai fait ma propre solution par l'ajout d'un apiErrors de la propriété de DS.Modèle et ensuite dans mon RestAdapter sous-classe (j'ai déjà eu besoin de mon propre) j'ai ajouté erreur rappels pour les appels Ajax pour createRecord et updateRecord que sauver les erreurs et de mettre le modèle dans les "nuls" de l'état, qui est censé signifier côté client ou côté serveur validations ont échoué.

Voici les extraits de code:

Cela peut aller dans application.js ou de quelque autre fichier de niveau supérieur:

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

Cela va dans l'erreur rappels createRecord et updateRecord dans un RestAdapter sous-classe:

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X