13

異なる URL エンドポイントからのデータで構成される単一のバックボーン モデルを使用したいと考えています。1 つのモデル内で複数の URL を指定することはできますか? AJAX を手動で呼び出すことは避けたいと思います。

これまで、私はjQuery Deferredsを使用して複数の URL を呼び出し、それらの結果を 1 つのオブジェクトに合成してきました。

これまでのところ、2 つのオプションが考えられます。URL ごとに部分モデルを使用してバックボーン モデルを構築するか、1 つの URL を使用してからオーバーライドModel.fetch()して他の URL を呼び出すかです。しかし、どちらも私を快適にしません。

(または、API 開発者に賄賂を渡して、マージされた URL エンドポイントを提供することもできます...)

4

2 に答える 2

8

あなたが提案した両方の方法はかなり合理的だと思いますが、個人的にはfetchアプローチに投票します。

ネストされたモデルを使用すると、「箱から出して」作業できるという利点があります。つまり、すべてのサーバー <=> クライアント マッピングに 1 つのモデルを使用することで、メソッドを変更する必要がなくなりますBackbone.Model。ただし、このアプローチの問題は、複数のモデルの集まりになってしまうことです。

とにかくそれが理にかなっている場合 (データの取得は別として)、ネストされたモデルに固執します。しかし、データ取得コードをシンプルに保つために、コードの残りの部分を 1 つのモデルだけでなく、複数のモデルで動作させることを強制している場合もあります。データ取得コードを複雑にし、他のすべてをシンプルに保ちたい場合は、上書きする方がよいでしょうfetch

fetchそれは、データとリモート URL の間の 1 対 1 のマッピングを介してデータを取得することです。代わりに1 対多のマッピングが必要fetch場合は、デフォルトの動作をオーバーライドするだけで十分です。fetchさらに、名前が isn ではないため、オーバーライドしてもかなり安全であることがわかります_fetch。また、Backbone はアンダースコア スタイルを使用して疑似プライベート メソッドに名前を付けます (例: _validate)。

それでもこれらのアプローチのいずれかが気に入らない場合は、別のオプションが 1 つあります:requestイベントです。Backbone の最新バージョンにはrequest、 が開始されるたびにトリガーされるという新しいイベントfetchがあります。これが意味することは、次のように、プライマリ データの要求に応答してセカンダリ データを取得するイベント ハンドラーをセットアップできるということです。

Backbone.Model.extend({
    initialize: function() {
        this.on('request', this.handleRequest);
        _.bindAll(this, 'handleTriggeredResponse');
    },
    handleRequest: function() {
        $.ajax({url: secondDataUrl, complete: this.handleTriggeredResponse});
        $.ajax({url: tertiaryDataUrl, complete: this.handleTriggeredResponse});
    },
    handleTriggeredResponse: function(response) {
        this.set(response.data);
    },
    url: firstDataUrl
});
于 2013-01-23T04:46:38.663 に答える
-1

別の解決策があります。デフォルトの Backbone.ajax 関数を、URL の配列またはハッシュをサポートする高度な jquery ajax 実行でオーバーライドします。データを並行してロードし、すべてのリクエストが完了すると制御をバックボーン モデルに戻します。

ajaxForArray = ->
  options = _.first arguments
  $.when.apply $, options.url.map (url) ->
    $.ajax _.merge _.omit(options, ['url', 'success']), {url}
  .done ->
    resp =
      if options.url.length > 1
        _.slice(arguments).map (arg) -> _.first arg
      else
        _.first arguments
    options.success? resp

ajaxForHash = ->
  options = _.first arguments
  pairs = _.transform options.url, (memo, url, key) ->
    memo.push {key, url}
  , []
  $.when.apply $, pairs.map (pair) ->
    $.ajax _.merge _.omit(options, ['url', 'success']), url: pair.url
  .done ->
    resp = _.slice(arguments).reduce (memo, arg, i) ->
      memo[pairs[i].key] = _.first arg
      memo
    , {}
    options.success? resp

Backbone.ajax = ->
  options = _.first arguments
  if _.isArray options.url
    ajaxForArray.apply $, arguments
  else if _.isObject(options.url) and not _.isFunction options.url
    ajaxForHash.apply $, arguments
  else
    $.ajax.apply $, arguments

モデルは、次のように URL の配列で設定できます。

class ArrayBasedModel extends Backbone.Model
  url: ['/aoo', '/boo', '/coo']
  parse: (resp) ->
    super _.extend {}, resp[0], resp[1], resp[2]

またはURLのハッシュ、

class HashBasedModel extends Backbone.Model
  url: {aoo: '/aoo', boo: '/boo', coo: '/coo'}
  parse: (resp) ->
    super _.extend {}, resp.aoo, resp.boo, resp.coo

したがって、parse() がオーバーライドされた場合は、すべての ajax 呼び出しの結果をマージして Backbone.Model.parse() に渡す基本的なロジックを追加するだけです。

これにより、異なる URL のプロパティが 1 つのモデル属性で利用できるようになります。

于 2016-06-14T01:54:03.193 に答える