2012-10-25 11 views
5

Chciałbym móc użyć obiektu odroczonego jQuery do obsługi ładowania danych przez kolekcje i modele szkieletu. Czy istnieje sposób, w jaki mogę zmodyfikować argumenty dostarczone do wykonanych i niepowodzeniem wywołań zwrotnych, aby uwzględnić wystąpienie modelu lub kolekcji? Ja przewidując coś jak następuje:Czy mogę użyć metody deferred.pipe jQuery w celu zmodyfikowania argumentów dostarczonych do odwołanych/odrzuconych wywołań zwrotnych?

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

oczywiście, ponieważ filtr jest zwrócenie tablicy, wykonane zwrotna jest wywoływana z tablicy, zamiast wymienionych argumentów. O ile widzę, potok może jedynie modyfikować dostarczone argumenty, a nie dodawać. Wszelkie sugestie będą mile widziane.

Edytuj: To jest bardzo uproszczony przykład; odkąd zostało stworzone zamknięcie nad oryginalną kolekcją, mógłbym po prostu operować na tym. Jednak przypadek użycia jest taki, że wiele widoków kręgosłupa może opierać się na tych samych pobieranych danych, więc chciałbym móc po prostu dostarczyć obiekt odroczony jQuery do tych widoków, zamiast zarówno instancji Odroczona, jak i kolekcji.

Kolejna edycja: wysłano poniżej rozwiązanie, ale wszelkie inne sugestie są mile widziane.

Odpowiedz

2

Znalazłem sposób można to osiągnąć poprzez metodę .pipe powrócić nowy $ .Deferred że natychmiast rozwiązany przy użyciu zmodyfikowanych argumenty:

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, aby rozszerzyć oryginalne jqXhr o nowe $ .Deferred, zachowując obsługę wszystkich metod specyficznych dla AJAX (.success, .abort, itp.). – philm

1

Rozwiązanie bardzo podobna do swojej odpowiedzi, ale bez rury, ponieważ w rzeczywistości nie trzeba filtrować wyniki: I bezpośrednio powrócić nowy odroczony od Backbone.sync zamiast rurociągów zdecydowanym odroczone

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

a Fiddle http://jsfiddle.net/d8FqA/

Prostszy wariant, jeśli jesteś gotów mieć this związany z modelu/odbioru w swoich wywołań zwrotnych, które pozostawia nietknięte podpisów funkcyjne:

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/

który prowadzi nas do zabicia model jako Ramy do żądania 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

Interesujące ... zdecydowanie podobne rozwiązanie. Jedno, co moim zdaniem może przynieść oba rozwiązania, to rozszerzenie pierwotnego obiektu jqXhr o nowe odroczenia, tak, że odpowiedź z Backbone.sync wcale się nie zmieni (z wyjątkiem obietnicy) np.) Return $ .extend (true, xhr, dfd); – philm

+0

@philm Myślę, że możemy uprościć wiele rzeczy, używając kontekstu w wywołaniach zwrotnych i zostawiając obiekt xhr w spokoju. Zaktualizowałem moją odpowiedź za pomocą rozwiązania: – nikoshr

+0

Jednym z problemów, które przedstawiamy, jest to, że jeśli czekamy na rozstrzygnięcie wielu odroczeń, to do której kolekcji zostanie powiązany kontekst? ex :) var col1 = new Bacbkone.Collection(), col2 = new Backbone.Collection(); $ .when (col1.fetch(), col2.fetch()). then then (function() {...}); – philm

Powiązane problemy