3

この質問は Backbone 0.9.2 に関するものでした

Backbone 0.9.10 にアップグレードしてから、代わりに Backbone.sync をオーバーライドすることを選択しましたが、これは魅力的に機能します。

  • 2012 年 12 月- (v0.9.9) Backbone.wrapError が削除されました。
  • 2013 年 2 月- 次のバージョンの Backbone で WrapError が復活するようですが、backbone.sync をオーバーライドするのが最善策です。


(長々と読んですみません)

私は Backbone.wrapError 関数を変更していますが、行に困惑しています。行が何をするかは知っていますが、なぜそれが必要なのかはわかりません。

  resp = model === originalModel ? resp : model;
  • resp は最終的に textStatus/errorType になります。つまり、「エラー」「タイムアウト」「解析エラー」です。
  • モデルは XHR リクエスト オブジェクトです
  • originalModel は、最終的にこの関数を呼び出した Backbone.Model インスタンスへの参照です。

Backbone.wrapError の機能、戻り値、使用方法についてはよく理解していますが、上記の行の目的を理解できないようです。


Backbone のドキュメントには、wrapError は「オプションのエラー コールバックをフォールバック エラー イベントでラップする」と記載されていますが、これは事実です。さらに、Backbone.wrapError はライブラリで fetch、save、destroy、および reset 関数内から 4 回呼び出され、AJAX エラーがライブラリによって見過ごされないようにすることを学びました。たとえば、AJAX エラー コールバックが fetch メソッドに渡された場合、いくつかのパラメーターが渡されて実行されます。そうでない場合、モデルは同じいくつかのパラメーターが渡されたエラー イベントをトリガーします。

呼び出しの例:

options.error = Backbone.wrapError(options.error, model, options);

Backbone.wrapError:

  Backbone.wrapError = function(onError, originalModel, options) {
    return function(model, resp) {
      resp = model === originalModel ? resp : model;
      if (onError) {
        onError(originalModel, resp, options);
      } else {
        originalModel.trigger('error', originalModel, resp, options);
      }
    };
  };

この行 ( resp = model === originalModel ? resp : model;) で発生する問題は、model と resp が jQuery/Zepto エラー コールバック パラメータ リスト内の最初の 2 つのパラメータに対応することです。最初の問題は、これらのパラメーター (モデル、応答) の命名に関するものです。デバッグ中に、これらの 2 つのパラメーターがjqXHR/xhrとであることがわかったためtextStatus/errorTypeです。textStatus/errorType パラメーターは通常「エラー」になりますが、(ドキュメントによると)「タイムアウト」「解析エラー」などになることもあります。比較はmodel === originalModel意味がありません。XHR オブジェクトと Backbone.Model インスタンスの厳密な比較は常に失敗し、(resp) にmodel格納されます。responsemodelは実際には XHR 応答オブジェクトです...この行は私には無意味に思えますが、先に進んで変更した wrapError メソッドに含めました。

model === originalModel常に false と評価されるため、行は resp = model; の精巧なバージョンのように見えます。行を完全に削除するだけで、modelパラメーターをoriginalModel.trigger('error', originalModel, resp, options);の代わりに渡すことができるため、これは役に立ちませんresp

model === originalModeltrue と評価される可能性のあるインスタンスはありますか?

Backbone.js、AJAX の経験が豊富な人は、この行が必要な理由について回答/説明を持っていますか?

4

1 に答える 1

4

TLDR/クリフ:

以下の奇妙な小さな行は、モデル レベルでの検証の失敗、または fetch、save、または destroy メソッド (すべて Backbone.sync を呼び出す) からの失敗した AJAX 呼び出しから、エラー コールバックがトリガーされた天気を判断するために使用されます。失敗が検証によるものである場合、resp 変数は変更されません。これは、resp が検証によって返された有用な情報 (エラー配列やエラーに関する文字列など) を既に保持している必要があるためです。失敗が不適切な AJAX リクエストによるものである場合、XHR オブジェクトは利用可能な最も有益なアイテムであるため、resp に格納されます。残念ながら、XHR はモデルとしてこの関数に渡され、バックボーンのドキュメントでは、このパラメーターが常にモデルを表しているとは限らないことを指摘していません。resp は、エラーに関する有用な応答情報を保持するためのものであり、エラー コールバックまたはスローされたエラー イベントに送信されます。


わかった。この奇妙な行についていくつかのことを学びました。

resp = model === originalModel ? resp : model;

バックボーンには、AJAX エラーと検証エラーがあります。便利なことに、Backbone は両方のエラーを同じ関数 (AJAX エラー コールバック) に注ぎ込みます。問題は、これらの関数に渡される引数が一貫していないことです。AJAX エラーが発生した場合、XHR オブジェクトは使用できますが、検証エラー中は使用できません。

  • コールバックが存在しない場合、Backbone は、エラー コールバックに渡されたのと同じパラメータで「エラー」イベントをスローします。(以下の 7 行目と 9 行目)。

AJAX 要求が成功した後、必要に応じてモデルの検証関数を介して JSON データを渡すことができます。Backbone では、検証機能should return false or nothing at all when there are no errors. エラーがある場合は、次のような配列を返すのが一般的です。validate から返されたもの (通常はエラー メッセージ配列) はすべて、パラメーター['invalid username', 'password too long', 'etc...']として「ラップされた」エラー コールバックに渡され、モデル自体は!として渡されます。respmodel

_validate 関数は少しずさんで複数の return ステートメントがありますが、検証が失敗すると 9 行目にヒットします。_validate関数の 9 行目は、(thisモデル)、error(モデルの validate メソッドから返される)、options(ajax オプション、成功、エラー、タイムアウトなど) を渡します。これは、xhr(xmlhttprequest オブジェクト)、errorType('error'、'timeout'、'parse error' など)、options(ajax オプション) で渡される AJAX エラーとは異なります。

validate error:   error(model, validate_return_value, options)
    ajax error:   error(xhr, errorType, options)

1   _validate: function(attrs, options) {
2     if (options.silent || !this.validate) return true;
3     attrs = _.extend({}, this.attributes, attrs);
4     var error = this.validate(attrs, options);
5     if (!error) return true;
6     if (options && options.error) {
7*       options.error(this, error, options);
8     } else {
9       this.trigger('error', this, error, options);
10    }
11    return false;
12  }

上記の奇妙なコード行が必要なのは、この 1 つの関数が 2 つの異なるメソッドからのエラーを処理するためです。AJAX と検証。これら 2 つは異なるパラメーターを送信するため、これはそれらを正規化し、一貫したパラメーター リストでイベントをスローすることを意味します。

When a validation error occurs, the model does not changeそのため、modelエラー コールバックに渡されるは とまったく同じoriginalModelです。パラメータの目的はresp、エラー自体に関する情報を保持することです。AJAX エラーが発生した場合、'timeout' 'parse error' または 'error' は XHR オブジェクトほど有益ではありません。

この奇妙な小さな行は、エラー コールバックが_validate404 などの通常の AJAX エラーから、またはそれを介してアクセスされたかどうかを判断しますresp。フロントエンド テンプレートが表示するための有益で有用なデータである必要があります。結果のエラーが HTTP エラーによるものである場合、そのエラーに関する最も有用な情報は、MODEL パラメータとしてこの関数に渡される XHR オブジェクトです。

うまくいけば、wrapError および validate 関数への単純化されたアプローチ

   Backbone.wrapError = function(ajax_error_callback, model_or_xhr, ajax_options) {
      return function(model_or_xhr, error_info) {
        if there was an ajax error, error_info = the xhr object
        if there was a validation error, error_info = whatever was returned from validate
        if there's an error callback {
          run the error callback with (the original model, error_info, ajax_options)  as parameters
        if there is not an error callback
          throw an event called 'error' with (the original model, error_info, ajax_options) as parameters
        }
      };
    };

オリジナル:

   Backbone.wrapError = function(onError, originalModel, options) {
      return function(model, resp) {
        resp = model === originalModel ? resp : model;
        if (onError) {
    *      onError(originalModel, resp, options);
        } else {
          originalModel.trigger('error', originalModel, resp, options);
        }
      };
    };

* は、エラー コールバックがここから呼び出されたことを示します。

于 2012-09-13T19:51:23.337 に答える