42

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は正しい方向に進んでいるようです。

4

4 に答える 4

42

今週末、私は同じことを理解しようとしていました。Luke が言ったことから外れて、最新のコミット(12 月 11 日) の ember-data ソースを詳しく調べました。

TLDR; ember-data の更新/作成エラーを処理するには、インスタンスでbecameError()とを定義するだけです。RESTadapter の AJAX エラー コールバックによってトリガーされるカスケードは、最終的に、定義したこれらの関数を呼び出します。becameInvalid(errors)DS.Model

例:

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 はここで定義され、応答に応じてストアの recordWasInvalid または 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.recordWasInvalidand (ここで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

これが他の誰かに役立つことを願っています。ドキュメントは確かにこれを反映していません。

于 2012-12-12T17:30:58.553 に答える
8

DS.RESTAdapterこのコミットでもう少しエラー処理が追加されましたが、まだエラー処理に関する優れた推奨事項がある段階には達していません。

Ember-data を使って今日アプリを本番環境に置くほど野心的/熱狂的である場合 (私もそうでした!)、API で障害が発生する可能性が非常に低いことを確認することをお勧めします。つまり、クライアント側でデータを検証します。

今後数か月以内に、この質問をより良い回答で更新できることを願っています。

于 2012-11-23T05:10:09.317 に答える
3

私はちょうどそのような状況に遭遇しました.これがすでにどこかで説明されているかどうかはわかりません.

私は使っている:

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

モデルは当初、検証 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')
        }
    }
}
});

テンプレートには、対応するハンドルバーが追加されています。(入力検証の場合、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を使用することが重要です

したがって、このようにして、属性をクライアント側で検証し、サーバー側で再度検証することができます。

免責事項 : これが最善の方法かどうかはわかりません!

于 2014-02-27T10:27:10.383 に答える
2

現在、在庫のEmber-Dataに適切なソリューションがないため、DS.Modelにプロパティを追加して独自のソリューションを作成し、apiErrorsRestAdapterサブクラス(すでに独自のサブクラスが必要)で、Ajax呼び出しにエラーコールバックを追加しました。エラーが発生し、モデルが「無効」状態になります。これは、クライアント側またはサーバー側の検証が失敗したことを意味します。createRecordupdateRecord

コードスニペットは次のとおりです。

これは、application.jsまたはその他のトップレベルファイルに含めることができます。

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

これは、RestAdapterサブクラスのエラーコールバックにcreateRecord含まれます。updateRecord

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');
}
于 2012-12-04T18:04:22.917 に答える