Xử lý jQuery.ajax tiếp tục trả lời: Thành công:


309

Tôi đã làm việc với jQuery và AJAX được 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.

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

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

Thành công: (.ajax () tùy chọn): Một hàm được gọi nếu yêu cầu thành công.

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

Câu trả lời:


469

successđã là tên truyền thống của cuộc gọi lại thành công trong jQuery, được định nghĩa là một tùy chọn trong lệnh gọi ajax. Tuy nhiên, vì việc thực hiện các $.Deferredscuộc gọi lại tinh vi hơn và phức tạp hơn, donelà cách ưa thích để 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.

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

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

Ví dụ: đã hoàn thành:

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

Điều tuyệt vời donelà giá trị trả về $.ajaxbây giờ là một lời hứa hoãn lại có thể bị ràng buộc với bất kỳ nơi nào khác trong ứng dụng của bạn. Vì vậy, hãy nói rằng 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ì đi qua trong chức năng thành công của bạn như một tùy chọn để các chức năng mà làm cho cuộc gọi ajax này, bạn chỉ có thể có chức năng trả lại $.ajaxbản thân và ràng buộc callbacks của bạn với done, fail, then, hoặc bất cứ điều gì. Lưu ý rằng đó alwayslà một cuộc gọi lại sẽ chạy cho dù yêu cầu thành công hay thất bại. donesẽ 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 vấn đề này về khả năng bảo trì là bạn đã bọc cơ chế ajax của mình trong một chức năng dành riêng cho ứng dụng. Nếu bạn quyết định bạn cần $.ajaxcuộc gọi của mình để hoạt động khác trong tương lai hoặc bạn sử dụng một phương thức ajax khác hoặc bạn rời khỏi jQuery, bạn chỉ phải thay đổi xhr_getđịnh nghĩa (chắc chắn sẽ trả lại lời hứa hoặc ít nhất là một donephương thức, trong trường hợp của 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ó rất nhiều điều nữa (mát hơn nhiều) bạn có thể làm với $.Deferredmột trong số đó là sử dụng pipeđể kích hoạt lỗi trên máy chủ được báo cáo, ngay cả khi $.ajaxyêu cầu 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/c Category / deferred-object /

LƯU Ý : Kể từ jQuery 1.8, pipeđã không được khuyến khích sử dụng thentheo cách chính xác như vậy.


2
Tôi tự hỏi làm thế nào các tương tác của success:/ .done()được xác định, nếu có. Eg success:chỉ là thực hiện như .done()những ngày đầu tiên ?

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

1
Bài viết rất hay! Btw, trong cuộc gọi lại đường ống, bạn không nên gọi hàm ống với tham số jqXHR để kiểm tra phản hồi trạng thái? Ví dụ: .pipe (hàm (dữ liệu, textStatus, jqXHR) {if (jqXHR.status == 200) {...
Eder

@Eder Kịch bản tôi đang xử lý với việc sử dụng pipenày là một trong đó yêu cầu tự thành công nhưng tập lệnh trên máy chủ không trả về những gì bạn đang tìm kiếm. Bạn có thể không muốn ném 404 hoặc 500 thực tế hoặc bất cứ thứ gì về phía máy chủ vì bạn muốn phân biệt một cách có ý nghĩa giữa phản hồi http và phản hồi của ứng dụng. Đặt mã phản hồi trong JSON và sau đó sử dụng cách pipenày cho phép bạn xử lý các loại lỗi khác nhau với nhiều sắc thái hơn.
glortho

Một lợi ích quan trọng khác của việc sử dụng lời hứa là mã của bạn trở nên dễ đọc hơn nhiều và bạn tránh được 'địa ngục gọi lại'. Điều này đặc biệt đúng khi bạn có nhiều cuộc gọi lại mà bạn muốn chạy từng cuộc gọi sau khi kết thúc trước đó. Với lời hứa, nó sẽ trông giống như myPromiseCall.then (..). Sau đó (..) thay vì cấu trúc phức tạp của các cuộc gọi lại được sử dụng với tùy chọn thành công.
Sinh ra ToCode

5

Nếu bạn cần async: falsetrong ajax của bạn, bạn nên sử dụng successthay vì .done. Khác bạn tốt hơn để sử dụng .done. Đây là từ trang web chính thức của jQuery :

Kể từ jQuery 1.8, việc sử dụng async: false với jqXHR ($ .Deferred) không được chấp nhận; bạn phải sử dụng các tùy chọn gọi lại thành công / lỗi / hoàn thành thay vì các phương thức tương ứng của đối tượng jqXHR, chẳng hạn như jqXHR.done () .


Ai đề cập đến async:false?
Liam

$.ajax({ url: req_url, ..., async: false, success: function (result, status, req) { }, error: function (jqXHR, status) { } });
AmirHossein Manian 17/2/19

0

Từ Tài liệu JQuery

Các đối tượng jqXHR được trả về bởi $.ajax()jQuery 1.5 thực hiện giao diện Promise, cung cấp cho chúng tất cả các thuộc tính, phương thức và hành vi của một Promise (xem đối tượng Trì hoãn để biết thêm thông tin). Các phương thức này nhận một hoặc nhiều đối số hàm được gọi khi $.ajax()yêu cầu kết thúc. Điều này cho phép bạn chỉ định nhiều cuộc gọi lại trên một yêu cầu và thậm chí chỉ định cuộc gọi lại sau khi yêu cầu có thể đã hoàn thành. (Nếu yêu cầu đã hoàn tất, cuộc gọi lại sẽ được kích hoạt ngay lập tức.) Các phương thức Promise có sẵn của đối tượng jqXHR bao gồm:

jqXHR.done(function( data, textStatus, jqXHR ) {});

Một cấu trúc thay thế cho tùy chọn gọi lại thành công, tham khảo để deferred.done()biết chi tiết thực hiện.

jqXHR.fail(function( jqXHR, textStatus, errorThrown ) {});

Một cấu trúc thay thế cho tùy chọn gọi lại lỗi, .fail()phương thức thay thế phương thức .error () không dùng nữa. Tham khảo deferred.fail () để biết chi tiết thực hiện.

jqXHR.always(function( data|jqXHR, textStatus, jqXHR|errorThrown ) { }); 

(được thêm vào trong jQuery 1.6) Một cấu trúc thay thế cho tùy chọn gọi lại hoàn chỉnh, .always()phương thức thay thế .complete()phương thức không dùng nữa .

Đáp lại yêu cầu thành công, các đối số của hàm giống như các đối số của .done(): data, textStatus và đối tượng jqXHR. Đối với các yêu cầu không thành công, các đối số giống như của .fail(): đối tượng jqXHR, textStatus và errorThrown. Tham khảo để deferred.always()biết chi tiết thực hiện.

jqXHR.then(function( data, textStatus, jqXHR ) {}, function( jqXHR, textStatus, errorThrown ) {});

Kết hợp chức năng của các phương thức .done().fail(), cho phép (kể từ jQuery 1.8), Promise bên dưới được thao tác. Tham khảo hoãn lại .then()để biết chi tiết thực hiện.

Thông báo khấu hao: Các jqXHR.success(), jqXHR.error()và các jqXHR.complete()cuộc gọi lại được loại bỏ kể từ jQuery 3.0. Bạn có thể sử dụng jqXHR.done(), jqXHR.fail()jqXHR.always()để thay thế.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.