2012-10-25 8 views
5

Tôi muốn có thể sử dụng đối tượng Trì hoãn của jQuery để vận hành dữ liệu tải thông qua Bộ sưu tập và Mô hình Backbone. Có cách nào tôi có thể sửa đổi các đối số được cung cấp cho các callbacks đã thực hiện và không thành công để bao gồm cá thể Model hoặc Collection không? Tôi đang hình dung một cái gì đó như sau:Tôi có thể sử dụng phương thức deferred.pipe của jQuery để sửa đổi các đối số được cung cấp cho các cuộc gọi lại không giải quyết/thất bại không?

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

Tất nhiên, vì bộ lọc trả về một mảng, gọi lại được thực hiện với một mảng chứ không phải đối số được liệt kê. Theo như tôi thấy, đường ống chỉ có thể sửa đổi các đối số được cung cấp, chứ không phải thêm. Mọi lơi đê nghị đêu nên được đanh gia cao.

Chỉnh sửa: Đây là một ví dụ rất đơn giản; kể từ khi một đóng cửa được tạo ra trên bộ sưu tập ban đầu, tôi chỉ có thể hoạt động trên đó. Tuy nhiên, trường hợp sử dụng là nhiều khung nhìn Backbone có thể dựa vào cùng một dữ liệu đang được tìm nạp, vì vậy tôi muốn có thể chỉ cung cấp đối tượng jQuery Deferred cho các khung nhìn này, chứ không phải cả trường hợp hoãn và bộ sưu tập.

Một chỉnh sửa khác: Đăng giải pháp bên dưới nhưng mọi đề xuất khác đều được chào đón.

Trả lời

2

tôi đã tìm thấy tôi có thể thực hiện điều này bằng cách có phương pháp .pipe trả về một mới $ .Deferred được ngay lập tức giải quyết bằng cách sử dụng tham số chỉnh sửa:

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 để mở rộng jqXhr ban đầu với $ .Deferred mới, duy trì hỗ trợ cho tất cả các phương thức AJAX cụ thể (.success, .abort, v.v.). – philm

1

Một giải pháp rất giống với câu trả lời của bạn, nhưng không có đường ống, vì bạn không thực sự cần để lọc kết quả: tôi trực tiếp trả lại một mới bị trì hoãn từ Backbone.sync thay vì đường ống một giải quyết chậm

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

Và một Fiddle http://jsfiddle.net/d8FqA/

Một biến thể đơn giản hơn nếu bạn sẵn sàng để có this ràng buộc với mô hình/bộ sưu tập trong callbacks của bạn, mà lá chữ ký chức năng bị ảnh hưởng:

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/

đó dẫn chúng ta để vượt qua các mô hình như ngữ cảnh để yêu cầu 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

Thú vị ... chắc chắn là một giải pháp tương tự. Một điều tôi nghĩ rằng cả hai giải pháp có thể được hưởng lợi từ sẽ mở rộng đối tượng jqXhr ban đầu với các giá trị hoãn lại mới, sao cho phản hồi từ Backbone.sync không thay đổi chút nào (ngoại trừ lời hứa).) Return $ .extend (đúng, xhr, dfd); – philm

+0

@philm Tôi nghĩ rằng chúng ta có thể đơn giản hóa mọi thứ bằng cách sử dụng ngữ cảnh trong các cuộc gọi lại và để riêng đối tượng xhr. Cập nhật câu trả lời của tôi với một giải pháp – nikoshr

+0

Một trong những vấn đề này trình bày là nếu chúng ta chờ đợi nhiều trì hoãn để được giải quyết, thì bộ sưu tập nào sẽ bối cảnh? ví dụ: var col1 = new Bacbkone.Collection(), col2 = new Backbone.Collection(); $ .when (col1.fetch(), col2.fetch()). (hàm() {...}); – philm