penanganan jQuery.ajax melanjutkan tanggapan: "sukses:" vs ".done"?

309

Saya telah bekerja dengan jQuery dan AJAX selama beberapa minggu sekarang dan saya melihat dua cara berbeda untuk 'melanjutkan' skrip setelah panggilan dibuat: success:dan .done.

Dari sinopsis dari dokumentasi jQuery kita dapatkan:

.done (): Deskripsi: Tambahkan penangan yang akan dipanggil ketika objek Ditangguhkan diselesaikan.

success: (.ajax () option): Suatu fungsi yang dipanggil jika permintaan berhasil.

Jadi, keduanya melakukan sesuatu setelah panggilan AJAX selesai / diselesaikan. Bisakah saya menggunakan satu atau yang lainnya secara acak? Apa perbedaannya dan kapan yang satu digunakan dan yang lainnya?

Claudio
sumber

Jawaban:

469

successtelah menjadi nama tradisional dari callback sukses di jQuery, didefinisikan sebagai opsi dalam panggilan ajax. Namun, sejak implementasi $.Deferredsdan callback yang lebih canggih, doneadalah cara yang disukai untuk mengimplementasikan callback yang sukses, karena dapat dipanggil pada semua deferred.

Misalnya, sukses:

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

Misalnya dilakukan:

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

Yang menyenangkan tentang donenilai pengembalian $.ajaxsekarang adalah janji yang ditangguhkan yang dapat terikat ke tempat lain di aplikasi Anda. Jadi katakanlah Anda ingin melakukan panggilan ajax ini dari beberapa tempat yang berbeda. Bukan lewat fungsi keberhasilan Anda sebagai pilihan untuk fungsi yang membuat panggilan ajax ini, Anda hanya dapat memiliki fungsi kembali $.ajaxitu sendiri dan mengikat callback Anda dengan done, fail, then, atau apa pun. Perhatikan bahwa alwaysini adalah panggilan balik yang akan berjalan apakah permintaan berhasil atau gagal. donehanya akan terpicu pada kesuksesan.

Sebagai contoh:

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

Manfaat penting dari ini dalam hal rawatan adalah bahwa Anda telah membungkus mekanisme ajax Anda dalam fungsi spesifik aplikasi. Jika Anda memutuskan bahwa Anda memerlukan $.ajaxpanggilan Anda untuk beroperasi secara berbeda di masa depan, atau Anda menggunakan metode ajax yang berbeda, atau Anda menjauh dari jQuery, Anda hanya perlu mengubah xhr_getdefinisi (pastikan untuk mengembalikan janji atau setidaknya donemetode, di kasus contoh di atas). Semua referensi lain di seluruh aplikasi dapat tetap sama.

Ada banyak lagi (jauh lebih keren) hal yang dapat Anda lakukan $.Deferred, salah satunya adalah menggunakan pipeuntuk memicu kegagalan pada kesalahan yang dilaporkan oleh server, bahkan ketika $.ajaxpermintaan itu sendiri berhasil. Sebagai contoh:

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

Baca lebih lanjut di $.Deferredsini: http://api.jquery.com/category/deferred-object/

CATATAN : Pada jQuery 1.8, pipetelah tidak digunakan lagi karena menggunakan thencara yang persis sama.

glortho
sumber
2
Saya bertanya-tanya bagaimana interaksi dari success:/ .done()didefinisikan, jika sama sekali. Misalnya success:baru diimplementasikan sebagai yang pertama .done()hari ini?
6
Maksud Anda jika Anda memiliki keduanya success:dan .donemelakukan panggilan ajax? Pertanyaan bagus. Karena semua panggilan balik lainnya dipanggil sesuai urutannya, tebakan saya adalah ya, successbaru dipanggil dulu.
glortho
1
Posting yang sangat bagus! Btw, di callback pipa, bukankah seharusnya Anda memanggil fungsi pipa dengan parameter jqXHR untuk memeriksa respon status? Contoh: .pipe (fungsi (data, textStatus, jqXHR) {if (jqXHR.status == 200) {...
Eder
@Eder Skenario yang saya bahas dengan penggunaan ini pipeadalah salah satu di mana permintaan itu sendiri berhasil tetapi skrip di server tidak mengembalikan apa yang Anda cari. Anda mungkin tidak ingin membuang 404 atau 500 yang sebenarnya atau apa pun di sisi server karena Anda ingin membedakan antara respons http dan respons aplikasi secara bermakna. Mengatur kode respons di JSON dan kemudian menggunakan pipecara ini memungkinkan Anda menangani berbagai jenis kesalahan dengan lebih banyak nuansa.
glortho
Manfaat penting lain dari menggunakan janji adalah bahwa kode Anda menjadi lebih mudah dibaca dan Anda menghindari 'panggilan balik neraka'. Ini terutama benar ketika Anda memiliki beberapa panggilan balik yang ingin Anda jalankan masing-masing setelah sebelumnya selesai. Dengan janji-janji itu akan terlihat seperti myPromiseCall.then (..). Lalu (..) bukannya bersarang struktur callback rumit yang digunakan dengan opsi sukses.
BornToCode
5

Jika Anda membutuhkan async: falsedi ajax Anda, Anda harus menggunakan successbukan .done. Lain Anda lebih baik menggunakan .done. Ini dari situs resmi jQuery :

Pada jQuery 1.8, penggunaan async: false dengan jqXHR ($ .Deferred) sudah tidak digunakan lagi; Anda harus menggunakan opsi keberhasilan / kesalahan / panggilan balik lengkap alih-alih metode yang sesuai dari objek jqXHR seperti jqXHR.done () .

AmirHossein Manian
sumber
Siapa yang menyebut async:false?
Liam
$.ajax({ url: req_url, ..., async: false, success: function (result, status, req) { }, error: function (jqXHR, status) { } });
AmirHossein Manian
0

Dari Dokumentasi JQuery

Objek jqXHR dikembalikan pada $.ajax()saat jQuery 1.5 mengimplementasikan antarmuka Janji, memberi mereka semua properti, metode, dan perilaku Janji (lihat objek yang Ditangguhkan untuk informasi lebih lanjut). Metode-metode ini mengambil satu atau lebih argumen fungsi yang dipanggil ketika $.ajax()permintaan berakhir. Ini memungkinkan Anda untuk menetapkan beberapa panggilan balik pada satu permintaan, dan bahkan untuk menetapkan panggilan balik setelah permintaan tersebut selesai. (Jika permintaan sudah selesai, callback dipecat segera.) Metode Janji yang tersedia dari objek jqXHR meliputi:

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

Alternatif konstruksi untuk opsi callback sukses, lihat deferred.done()rincian implementasi.

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

Alternatif konstruksi untuk opsi panggilan balik kesalahan, .fail()metode ini menggantikan metode .error () yang tidak digunakan lagi. Rujuk ke deferred.fail () untuk detail implementasi.

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

(ditambahkan dalam jQuery 1.6) Sebuah konstruksi alternatif untuk opsi panggilan balik lengkap, .always()metode ini menggantikan metode yang tidak .complete()digunakan lagi .

Menanggapi permintaan yang berhasil, argumen fungsi adalah sama dengan argumen dari .done(): data, textStatus, dan objek jqXHR. Untuk permintaan yang gagal, argumennya sama dengan argumen dari .fail(): objek jqXHR, textStatus, dan errorThrown. Lihat deferred.always()untuk detail implementasi.

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

Menggabungkan fungsionalitas .done()dan .fail()metode, memungkinkan (pada jQuery 1.8) Janji yang mendasarinya untuk dimanipulasi. Lihat ditangguhkan .then()untuk detail implementasi.

Pemberitahuan Penghentian: The jqXHR.success(),, jqXHR.error()dan jqXHR.complete()callback dihapus pada jQuery 3.0. Anda dapat menggunakan jqXHR.done(), jqXHR.fail()dan jqXHR.always()sebagai gantinya.

Sasmit
sumber