5

jQuery の Deferred オブジェクトを使用して、バックボーン コレクションとモデルを介してデータのロードを操作できるようにしたいと考えています。モデルまたはコレクションのインスタンスを含めるために、完了および失敗のコールバックに提供される引数を変更する方法はありますか? 以下のようなものを想定しています。

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

もちろん、filter は配列を返すため、done コールバックは列挙された引数ではなく配列で呼び出されます。私の知る限り、パイプは提供された引数を変更することしかできず、追加することはできません。任意の提案をいただければ幸いです。

編集:これは非常に単純化された例です。元のコレクションに対してクロージャが作成されるため、それを操作するだけで済みます。ただし、複数のバックボーン ビューがフェッチされる同じデータに依存している可能性があるため、Deferred とコレクション インスタンスの両方ではなく、jQuery Deferred オブジェクトをこれらのビューに提供できるようにしたいと考えています。

別の編集:以下に解決策を投稿しましたが、他の提案は大歓迎です。

4

2 に答える 2

2

.pipeメソッドが新しい$.Deferredを返すようにすることで、これを実現できることがわかりました。これは、変更された引数を使用してすぐに解決されます。

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);
};
于 2012-10-25T17:10:18.010 に答える
1

あなたの答えに非常に似た解決策ですが、実際には結果をフィルタリングする必要がないため、パイプはありません。解決された遅延をパイプする代わりに、Backbone.sync から新しい遅延を直接返します。

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/

コールバックでモデル/コレクションにバインドしたい場合の単純なバリエーションです。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/

于 2012-10-25T17:46:27.600 に答える