2012-01-12 31 views
264

Tôi đã làm việc với jQuery và AJAX trong vài tuần và tôi đã thấy hai cách khác nhau để 'tiếp tục' tập lệnh sau khi cuộc gọi được thực hiện: success:.done.Xử lý jQuery.ajax tiếp tục phản hồi: "thành công:" so với ".done"?

Từ tóm tắt từ jQuery documentation chúng tôi nhận được:

.done(): Mô tả: Thêm xử lý được gọi khi đối tượng thu nhập hoãn lại được giải quyết.

thành công: (.ajax() tùy chọn): Hàm sẽ được gọi nếu yêu cầu thành công.

Vì vậy, cả hai làm điều gì đó sau khi cuộc gọi AJAX đã được hoàn thành/giải quyết. Tôi có thể sử dụng một hoặc khác một cách ngẫu nhiên? Sự khác biệt là gì và khi nào được sử dụng thay cho cái kia?

Trả lời

399

success là tên truyền thống của hàm gọi lại thành công trong jQuery, được định nghĩa là tùy chọn trong cuộc gọi ajax. Tuy nhiên, kể từ khi thực hiện $.Deferreds và các cuộc gọi lại phức tạp hơn, done là cách ưu tiên để thực hiện các cuộc gọi lại thành công, vì nó có thể được gọi trên bất kỳ deferred nào.

Ví dụ, thành công:

$.ajax({ 
    url: '/', 
    success: function(data) {} 
}); 

Ví dụ, thực hiện:

$.ajax({url: '/'}).done(function(data) {}); 

Những điều tốt đẹp về done là giá trị trả về của $.ajax bây giờ là một lời hứa chậm có thể được liên kết với bất cứ nơi nào khác trong ứng dụng của bạn. Vì vậy, giả sử bạn muốn thực hiện cuộc gọi ajax này từ một vài nơi khác nhau. Thay vì truyền chức năng thành công của bạn như một tùy chọn cho hàm thực hiện cuộc gọi ajax này, bạn chỉ có thể trả lại hàm $.ajax chính nó và liên kết các cuộc gọi lại của bạn với done, fail, then hoặc bất kỳ thứ gì. Lưu ý rằng always là một cuộc gọi lại sẽ chạy cho dù yêu cầu thành công hay không thành công. done sẽ chỉ được kích hoạt khi thành công.

Ví dụ:

function xhr_get(url) { 

    return $.ajax({ 
    url: url, 
    type: 'get', 
    dataType: 'json', 
    beforeSend: showLoadingImgFn 
    }) 
    .always(function() { 
    // remove loading image maybe 
    }) 
    .fail(function() { 
    // handle request failures 
    }); 

} 

xhr_get('/index').done(function(data) { 
    // do stuff with index data 
}); 

xhr_get('/id').done(function(data) { 
    // do stuff with id data 
}); 

Một lợi ích quan trọng của việc này về khả năng bảo trì là bạn đã quấn cơ chế ajax của bạn trong một chức năng ứng dụng cụ thể. Nếu bạn quyết định bạn cần gọi $.ajax để hoạt động khác trong tương lai hoặc bạn sử dụng phương pháp ajax khác hoặc bạn di chuyển khỏi jQuery, bạn chỉ phải thay đổi định nghĩa xhr_get (chắc chắn trả lại lời hứa hoặc ít nhất là done trong trường hợp ví dụ trên). Tất cả các tài liệu tham khảo khác trong suốt ứng dụng có thể vẫn giữ nguyên.

Có nhiều thứ khác (nhiều điều thú vị hơn) bạn có thể thực hiện với $.Deferred, một trong số đó là sử dụng pipe để kích hoạt lỗi do máy chủ báo cáo, ngay cả khi yêu cầu $.ajax tự thành công.Ví dụ:

function xhr_get(url) { 

    return $.ajax({ 
    url: url, 
    type: 'get', 
    dataType: 'json' 
    }) 
    .pipe(function(data) { 
    return data.responseCode != 200 ? 
     $.Deferred().reject(data) : 
     data; 
    }) 
    .fail(function(data) { 
    if (data.responseCode) 
     console.log(data.responseCode); 
    }); 
} 

xhr_get('/index').done(function(data) { 
    // will not run if json returned from ajax has responseCode other than 200 
}); 

Đọc thêm về $.Deferred đây: http://api.jquery.com/category/deferred-object/

LƯU Ý: Tính đến jQuery 1.8, pipe đã phản đối ủng hộ sử dụng then chính xác theo cùng một cách.

+2

Tôi tự hỏi cách tương tác của 'thành công:' /'.done() 'được xác định, nếu có. Ví dụ. là 'thành công:' chỉ được thực hiện như là '.done()' đầu tiên? –

+5

Bạn có nghĩa là nếu bạn có cả hai 'thành công:' và '.done' trên một cuộc gọi ajax? Câu hỏi hay. Vì tất cả các callbacks khác được gọi theo thứ tự mà chúng bị ràng buộc, tôi đoán là có, 'success' chỉ được gọi trước. – glortho

+1

Có, điều đó thực sự có vẻ là trường hợp: http://jsfiddle.net/9L7dD/ – Adam

2

Nếu bạn cần async: false trong ajax, bạn nên sử dụng success thay vì .done. Khác bạn tốt hơn để sử dụng .done. Đây là từ jQuery official site:

Tính đến jQuery 1.8, việc sử dụng async: false với jqXHR ($ .Deferred) bị phản đối; bạn phải sử dụng thành công/lỗi/hoàn chỉnh tùy chọn callback thay vì các phương pháp tương ứng của đối tượng jqXHR như jqXHR.done().

Các vấn đề liên quan