2012-10-25 10 views
5

jQueryのDeferredオブジェクトを使用して、バックボーンコレクションとモデルを介してデータを読み込むことができるようにしたいと考えています。モデルやコレクションのインスタンスを含めるためにdoneおよびfailコールバックに渡される引数を変更する方法はありますか?フィルタは、配列を返すされているので、行ってコールバックがむしろ列挙引数よりも、配列で呼び出され、もちろんjQueryのdeferred.pipeメソッドを使用して、解決済みコールバックまたは失敗したコールバックに提供された引数を変更できますか?

var _sync = Backbone.sync; 

Backbone.sync = function() { 
    var jqXhr = _sync.apply(this, arguments); 

    var self = this; 
    return jqXhr.pipe(function() { 
     var cbArgs = [self]; 
     cbArgs.push.apply(cbArgs, arguments); 
     return cbArgs; 
    } 
} 

... 
var c = new Backbone.Collection(); 
c.url = "/path/to/resources"; 
c.fetch().then(function(collection, data, textStatus, jqXhr) { 
    // do stuff with collection 
}); 

:私は次のようなものを想定しています。私が見る限りでは、パイプは与えられた引数だけを変更することができ、追加することはできません。任意の提案をいただければ幸いです。

編集:これは非常に単純な例です。クロージャーが元のコレクションの上に作成されるので、私はそれを操作することができます。しかし、ユースケースでは、複数のBackbone Viewsが同じデータをフェッチされている可能性があるため、DeferredとCollectionインスタンスの両方ではなく、jQuery Deferredオブジェクトをこれらのビューに提供できます。

もう1つの編集:以下の解決策を掲載しましたが、他の提案は歓迎します。

私は.pipe方法はすぐに変更された引数を使用して解決される新しい$ .Deferredを返すことによって、これを達成することができます見つけた

答えて

2

var _sync = Backbone.sync; 

Backbone.sync = function() { 
    var jqXhr = _sync.apply(this, arguments); 

    var self = this; 
    var deferred = jqXhr.pipe(function() { 
     var cbArgs = [self]; 
     cbArgs.push.apply(cbArgs, arguments); 
     var deferred = new $.Deferred(); 
     return deferred.resolve.apply(deferred, cbArgs); 
    }); 
    return $.extend(true, jqXhr, deferred); 
}; 
+0

Edite d。新しい$ .DeferredでオリジナルのjqXhrを拡張し、すべてのAJAX固有のメソッド(.success、.abortなど)のサポートを維持します。 – philm

1

あなたの答えに非常に類似したソリューションを、しかしなしパイプ、あなたが実際に結果をフィルタリングする必要がないので、私は直接の代わりに解決延期

Backbone.originalSync = Backbone.sync; 
Backbone.sync = function(method, model, options) { 
    var xhr = Backbone.originalSync.call(this, method, model, options); 

    var dfd = $.Deferred(); 
    xhr.done(function() { 
     var cbArgs = [model].concat(_.toArray(arguments)); 
     dfd.resolve.apply(dfd, cbArgs); 
    }); 
    xhr.fail(function() { 
     var cbArgs = [model].concat(_.toArray(arguments)); 
     dfd.reject.apply(dfd, cbArgs); 
    }); 

    return dfd; 
}; 

とフィドルhttp://jsfiddle.net/d8FqA/

0123を配管Backbone.syncから延期新しいを返します

シンプルなバリエーションあなたは手つかずの関数のシグネチャを残し、あなたのコールバックでモデル/コレクションにバインドされthis、持っているために喜んでいる場合:としてモデルを渡すために私たちを導く

Backbone.originalSync = Backbone.sync; 
Backbone.sync = function(method, model, options) { 
    var xhr = Backbone.originalSync.call(this, method, model, options); 

    var dfd = $.Deferred(); 
    xhr.done(function() { 
     dfd.resolveWith(model, arguments); 
    }); 
    xhr.fail(function() { 
     dfd.rejectWith(model, arguments); 
    }); 

    return dfd; 
}; 

var c=new Backbone.Collection(); 
c.fetch().done(function() { 
    console.log(this); 
    console.log(arguments); 
}); 

http://jsfiddle.net/d8FqA/1/

をAjaxリクエストのコンテキスト:

Backbone.originalSync = Backbone.sync; 
Backbone.sync = function(method, model, options) { 
    options || (options={}) ; 
    options.context = model; 
    return Backbone.originalSync.call(this, method, model, options); 
}; 

var c=new Backbone.Collection(); 
c.fetch().done(function() { 
    console.log(this); 
}); 

http://jsfiddle.net/d8FqA/2/

+0

興味深い...間違いなく同様の解決策。私は両方のソリューションが恩恵を受けられると思うことの1つは、元のjqXhrオブジェクトを新しい遅延で拡張することで、Backbone.syncからの応答がまったく変わらないことです(約束を例外として)。return $ .extend true、xhr、dfd); – philm

+0

@philm私は、コールバック内のコンテキストを使って多くのことを単純化し、xhrオブジェクトだけを残すことができると思います。私の答えが解決策で更新されました – nikoshr

+0

この問題の1つは、複数の延期が解決されるのを待っている場合、どのコレクションがコンテキストにバインドされるのでしょうか?例:var col1 = new Bacbkone.Collection()、col2 = new Backbone.Collection(); $ .when(col1.fetch()、col2.fetch())。then(function(){...}); – philm

関連する問題