jQuery.ajax จัดการตอบสนองต่อ:“ สำเร็จ:” กับ“ .done” หรือไม่


309

ผมได้ทำงานกับ jQuery AJAX และไม่กี่สัปดาห์ที่ผ่านมาและตอนนี้ฉันเห็นสองวิธีที่แตกต่างกันเพื่อ 'ยังคง' สคริปต์ที่ครั้งหนึ่งเคยเรียกร้องได้รับการทำ: และsuccess:.done

จากบทสรุปจากเอกสาร jQueryเราได้รับ:

.done (): คำอธิบาย: เพิ่มตัวจัดการที่จะเรียกเมื่อวัตถุที่ถูกเลื่อนออกไปได้รับการแก้ไข

สำเร็จ: (.ajax () ตัวเลือก): ฟังก์ชั่นที่จะเรียกว่าถ้าคำขอประสบความสำเร็จ

ดังนั้นทั้งคู่จึงทำบางสิ่งหลังจากการโทร AJAX เสร็จสมบูรณ์ / แก้ไขแล้ว ฉันสามารถใช้แบบสุ่มอย่างใดอย่างหนึ่งได้หรือไม่ ความแตกต่างคืออะไรและเมื่อใช้อย่างใดอย่างหนึ่งแทนสิ่งอื่น

คำตอบ:


469

successเป็นชื่อดั้งเดิมของการโทรกลับสำเร็จใน jQuery ซึ่งกำหนดเป็นตัวเลือกในการโทร ajax อย่างไรก็ตามเนื่องจากการดำเนินการ$.Deferredsและการเรียกกลับที่ซับซ้อนมากขึ้นdoneเป็นวิธีที่ต้องการในการใช้การเรียกกลับที่ประสบความสำเร็จเนื่องจากสามารถเรียกdeferredใช้ได้

ตัวอย่างเช่นความสำเร็จ:

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

ตัวอย่างเช่นทำ:

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

สิ่งที่ดีเกี่ยวกับdoneคือ$.ajaxตอนนี้มูลค่าส่งคืนของตอนนี้เป็นสัญญาที่เลื่อนออกไปซึ่งสามารถผูกไว้กับที่อื่นในใบสมัครของคุณ สมมติว่าคุณต้องการโทร ajax นี้จากสถานที่ต่าง ๆ แทนที่จะผ่านในฟังก์ชั่นที่ประสบความสำเร็จของคุณเป็นตัวเลือกในการฟังก์ชั่นที่ทำให้การเรียก Ajax นี้คุณก็สามารถมีผลตอบแทนจากการทำงาน$.ajaxของตัวเองและผูกเรียกกลับของคุณด้วยdone, fail, thenหรืออะไรก็ตาม โปรดทราบว่าalwaysเป็นการติดต่อกลับที่จะทำงานไม่ว่าคำขอจะสำเร็จหรือล้มเหลว doneจะถูกเรียกใช้เมื่อประสบความสำเร็จเท่านั้น

ตัวอย่างเช่น:

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

ประโยชน์ที่สำคัญของสิ่งนี้ในแง่ของการบำรุงรักษาคือคุณได้ห่อกลไก ajax ไว้ในฟังก์ชั่นเฉพาะแอปพลิเคชัน หากคุณตัดสินใจที่คุณต้องการของคุณ$.ajaxเรียกร้องให้ดำเนินการแตกต่างกันในอนาคตหรือคุณใช้วิธีอาแจ็กซ์ที่แตกต่างกันหรือคุณย้ายออกจาก jQuery, คุณจะต้องเปลี่ยนxhr_getคำนิยาม (เป็นแน่ใจว่าจะกลับมาเป็นสัญญาหรืออย่างน้อยdoneวิธีการใน กรณีของตัวอย่างข้างต้น) ข้อมูลอ้างอิงอื่น ๆ ทั้งหมดในแอพสามารถยังคงเหมือนเดิม

ยังมีอีกหลายสิ่งที่คุณสามารถทำได้$.Deferred(หนึ่งที่น่าสนใจกว่า) ซึ่งหนึ่งในนั้นก็คือการใช้pipeเพื่อกระตุ้นให้เกิดความล้มเหลวในข้อผิดพลาดที่รายงานโดยเซิร์ฟเวอร์แม้เมื่อ$.ajaxคำขอนั้นสำเร็จ ตัวอย่างเช่น:

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

อ่านเพิ่มเติมเกี่ยวกับ$.Deferredที่นี่: http://api.jquery.com/category/deferred-object/

หมายเหตุ : ตั้งแต่ jQuery 1.8 pipeได้เลิกใช้งานไปแล้วในthenลักษณะเดียวกัน


2
ฉันสงสัยว่าปฏิสัมพันธ์ของsuccess:/ .done()ถูกกำหนดอย่างไรถ้าทั้งหมด เช่นจะsuccess:ใช้งานเป็นวันแรก.done()เหล่านี้หรือไม่

6
คุณหมายถึงถ้าคุณมีทั้งsuccess:และ.doneในการโทร ajax? คำถามที่ดี. เนื่องจากการโทรกลับอื่น ๆ ทั้งหมดถูกเรียกตามลำดับที่ถูกผูกไว้ฉันเดาว่าใช่แล้วsuccessจึงถูกเรียกก่อน
Glortho

1
โพสต์ที่ดีมาก! Btw ในการโทรกลับไปป์คุณไม่ควรเรียกฟังก์ชันไพพ์ด้วยพารามิเตอร์ jqXHR เพื่อตรวจสอบการตอบกลับสถานะใช่หรือไม่ Ex: .pipe (ฟังก์ชั่น (ข้อมูล textStatus, jqXHR) {if (jqXHR.status == 200) { ...
เอ๊ด

@Eder สถานการณ์ที่ฉันจัดการกับการใช้นี้pipeเป็นสิ่งหนึ่งที่คำขอประสบความสำเร็จ แต่สคริปต์บนเซิร์ฟเวอร์ไม่ได้ส่งคืนสิ่งที่คุณต้องการ คุณอาจไม่ต้องการโยน 404 หรือ 500 จริงหรืออะไรก็ตามในฝั่งเซิร์ฟเวอร์เพราะคุณต้องการแยกความแตกต่างระหว่างการตอบสนอง http และการตอบสนองของแอปพลิเคชันอย่างมีความหมาย การตั้งค่ารหัสตอบกลับใน JSON จากนั้นใช้pipeวิธีนี้ช่วยให้คุณสามารถจัดการข้อผิดพลาดชนิดต่าง ๆ ด้วยความแตกต่างกันเล็กน้อย
glortho

ประโยชน์ที่สำคัญอีกข้อหนึ่งของการใช้สัญญาคือรหัสของคุณจะอ่านได้มากขึ้นและคุณหลีกเลี่ยง 'callback hell' นี่เป็นเรื่องจริงโดยเฉพาะเมื่อคุณมีการเรียกกลับหลายครั้งที่คุณต้องการเรียกใช้แต่ละรายการหลังจากที่เสร็จสิ้นก่อนหน้า ด้วยคำสัญญามันจะดูเหมือน myPromiseCall.then (.. ). จากนั้น (.. ) แทนที่จะเป็นโครงสร้างที่ซับซ้อนซ้อนกันของการโทรกลับที่ใช้กับตัวเลือกความสำเร็จ
BornToCode

5

หากคุณต้องการasync: falseในอาแจ็กซ์ของคุณคุณควรจะใช้แทนsuccess .doneอื่น ๆ .doneที่คุณดีกว่าที่จะใช้ นี่คือจากเว็บไซต์อย่างเป็นทางการของ jQuery :

ในฐานะของ jQuery 1.8การใช้async: falseกับ jqXHR ($ .Deferred) ถูกคัดค้าน คุณต้องใช้ความสำเร็จ / ข้อผิดพลาด / สมบูรณ์ตัวเลือกการเรียกกลับแทนวิธีการที่สอดคล้องกันของวัตถุ jqXHR เช่นjqXHR.done ()


ใครพูดถึงasync:false?
เลียม

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

0

จากเอกสาร JQuery

อ็อบเจ็กต์ jqXHR ที่ส่งคืนโดย$.ajax()ณ jQuery 1.5 นำอินเตอร์เฟส Promise มามอบคุณสมบัติวิธีการและพฤติกรรมทั้งหมดของสัญญา (ดูที่วัตถุรอการตัดบัญชีสำหรับข้อมูลเพิ่มเติม) เมธอดเหล่านี้รับอาร์กิวเมนต์ของฟังก์ชันหนึ่งตัวหรือมากกว่าที่ถูกเรียกเมื่อการ$.ajax()ร้องขอสิ้นสุดลง วิธีนี้ช่วยให้คุณสามารถกำหนดการโทรกลับหลายครั้งในการร้องขอเดียวและแม้กระทั่งการกำหนดการโทรกลับหลังจากที่คำขอเสร็จสิ้น (หากคำขอเสร็จสมบูรณ์แล้วจะมีการโทรกลับทันที) วิธีการสัญญาที่ใช้ได้ของวัตถุ jqXHR รวมถึง:

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

โครงสร้างทางเลือกอื่นสำหรับตัวเลือกการเรียกกลับสำเร็จอ้างอิงdeferred.done()สำหรับรายละเอียดการใช้งาน

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

โครงสร้างทางเลือกอื่นสำหรับตัวเลือกการเรียกกลับข้อผิดพลาด.fail()วิธีแทนที่เมธอด .error () ที่คัดค้าน อ้างถึง deferred.fail () สำหรับรายละเอียดการใช้งาน

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

(เพิ่มเข้ามาใน jQuery 1.6) ความสร้างทางเลือกให้กับตัวเลือกการเรียกกลับสมบูรณ์.always()วิธีการแทนที่เลิกใช้.complete()วิธีการ

ในการตอบสนองต่อคำขอที่ประสบความสำเร็จอาร์กิวเมนต์ของฟังก์ชันจะเหมือนกับของ.done()data, textStatus และ jqXHR สำหรับคำร้องขอที่ล้มเหลวอาร์กิวเมนต์จะเหมือนกับของ.fail(): อ็อบเจ็กต์ jqXHR, textStatus และ errorThrown อ้างถึงdeferred.always()สำหรับรายละเอียดการใช้งาน

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

รวมการทำงานของ.done()และ.fail()วิธีการอนุญาต (เหมือน jQuery 1.8) สัญญาพื้นฐานที่จะจัดการ อ้างถึงรอการตัดบัญชี.then()สำหรับรายละเอียดการใช้งาน

ประกาศการเลิกใช้งาน: The jqXHR.success(), jqXHR.error()และjqXHR.complete()callbacks ถูกลบตั้งแต่ jQuery 3.0 คุณสามารถใช้ jqXHR.done(), jqXHR.fail()และjqXHR.always()แทน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.