HttpPromise Angular: perbedaan antara metode `success` /` error` dan argumen `then`

177

Menurut AngularJS doc , panggilan untuk $httpmengembalikan yang berikut:

Mengembalikan objek janji dengan metode standar lalu dan dua metode spesifik http: sukses dan kesalahan . The kemudian Metode membutuhkan dua argumen yang sukses dan error callback yang akan dipanggil dengan objek respon. Metode keberhasilan dan kesalahan mengambil argumen tunggal - fungsi yang akan dipanggil ketika permintaan berhasil atau gagal masing-masing. Argumen yang diteruskan ke fungsi-fungsi ini adalah representasi destruktif dari objek respons yang diteruskan ke metode saat itu.

Selain dari fakta bahwa responseobjek dirusak dalam satu kasus, saya tidak mendapatkan perbedaan di antara keduanya

  • keberhasilan / kesalahan callback disahkan untuk diteruskan sebagai argumen promise.then
  • callback disahkan sebagai argumen untuk promise.success/ promise.errormetode janji

Apakah ada? Apa gunanya dua cara berbeda ini untuk menyampaikan panggilan balik yang tampaknya identik?

ejoubaud
sumber

Jawaban:

156

NB Jawaban ini secara faktual salah; seperti yang ditunjukkan oleh komentar di bawah ini, sukses () memang mengembalikan janji semula. Saya tidak akan berubah; dan serahkan ke OP untuk mengedit.


Perbedaan utama antara 2 adalah bahwa .then()panggilan mengembalikan janji (diselesaikan dengan nilai yang dikembalikan dari panggilan balik) sementara .success()cara yang lebih tradisional mendaftarkan panggilan balik dan tidak mengembalikan janji.

Callback berbasis janji ( .then()) memudahkan untuk mengaitkan janji (melakukan panggilan, menginterpretasikan hasil, lalu melakukan panggilan lain, menginterpretasikan hasil, melakukan panggilan lain, dll.).

The .success()Metode adalah, metode kemudahan efisien ketika Anda tidak perlu panggilan rantai atau bekerja dengan API janji (misalnya, dalam routing).

Pendeknya:

  • .then() - kekuatan penuh API janji tetapi sedikit lebih bertele-tele
  • .success() - tidak mengembalikan janji tetapi menawarkan sintaks yang sedikit lebih ramah
pkozlowski.opensource
sumber
44
Perbedaan besar lain adalah bahwa thencallback mengambil satu argumen - respon - sementara successdan errormengambil masing-masing komponen respon sebagai arguments-- data, status, header, dan config.
Michelle Tilley
1
@BrandonTilley sepenuhnya benar, tetapi penulis pertanyaan sudah mengetahuinya jadi saya tidak merasa perlu mengulanginya di sini.
pkozlowski.opensource
45
Meskipun dokumentasi tidak mengatakannya secara eksplisit, kita dapat menyimpulkan bahwa .success()metode mengembalikan objek janji $ http asli, karena rantai $http(...).success(...).error(...)dimungkinkan. Jika, sepertinya masuk akal, kebalikannya $http(...).error(...).success(...)juga mungkin, maka .error()juga harus mengembalikan objek janji asli. Perbedaan yang membedakan .then()adalah bahwa ia mengembalikan janji baru .
Beetroot-Beetroot
2
Kode sumber dari angular.js dari layanan $ http: promise.success = function(fn) { promise.then(function(response) { fn(response.data, response.status, response.headers, config); }); return promise; };
Alex Che
6
Harap dicatat bahwa successsudah usang. Dari docs.angularjs.org/api/ng/service/$http#deprecation-notice The $http legacy promise methods success and error have been deprecated. Use the standard then method instead. If $httpProvider.useLegacyPromiseExtensions is set to false then these methods will throw $http/legacy error.
Sam Barnum
204

Sudah ada beberapa jawaban bagus di sini. Tapi ada baiknya untuk membawa pulang perbedaan dalam paralelisme yang ditawarkan:

  • success() mengembalikan janji semula
  • then() mengembalikan janji baru

Perbedaannya adalah then()drive operasi berurutan, karena setiap panggilan mengembalikan janji baru.

$http.get(/*...*/).
  then(function seqFunc1(response){/*...*/}).
  then(function seqFunc2(response){/*...*/})
  1. $http.get()
  2. seqFunc1()
  3. seqFunc2()

success() mendorong operasi paralel, karena penangan dirantai dengan janji yang sama.

$http(/*...*/).
  success(function parFunc1(data){/*...*/}).
  success(function parFunc2(data){/*...*/})
  1. $http.get()
  2. parFunc1(), parFunc2()secara paralel
event_jr
sumber
3
Perhatikan respons janji baru yang dikembalikan setelah thenhasil tercapai dalam successdan errormetode menghilang. Juga, untuk respons kesalahan http (mis. 404) thenin pertama http.then(ok, err).then(ok, err)akan diteruskan ke errhandler tetapi yang berikut akan masuk ke okhandler. Pada dasarnya http.success().error().success().error()adalah rantai tetapi janji $ q sangat berbeda karena mereka semua tentang janji dan urutan penanganan secara khusus (dan bukan penanganan permintaan http). Saya kesulitan memahami hal ini sampai saya mencermati.
Jimmont
1
@ Jimmont successdan errorbukan API normal dari janji, mereka melesat ke nilai kembali $ http ().
event_jr
Terima kasih @event_jr ini jelas bagi saya, dan memanggil dokumen. Yang tidak jelas (bagi saya) adalah bagaimana $ q dan $ http menyelesaikan masalah yang berbeda serta mengembalikan janji-janji baru vs melewati yang sama melalui - sebagaimana ditunjukkan dalam jawaban Anda (sangat membantu).
Jimmont
1
Apa yang Anda maksud dengan paralel, karena JS adalah single-threaded? Apakah maksud Anda bahwa urutan eksekusi adalah non-deterministik?
Derek
2
@Derek yang kedua successakan dieksekusi setelah yang pertama dieksekusi tetapi sebelum janji apa pun kembali dari itu diselesaikan sedangkan yang kedua thenakan menunggu. Jika Anda tidak mengembalikan janji maka keduanya berperilaku sama.
Tamlyn
114

Beberapa contoh kode untuk permintaan GET sederhana. Mungkin ini membantu memahami perbedaannya. Menggunakan then:

$http.get('/someURL').then(function(response) {
    var data = response.data,
        status = response.status,
        header = response.header,
        config = response.config;
    // success handler
}, function(response) {
    var data = response.data,
        status = response.status,
        header = response.header,
        config = response.config;
    // error handler
});

Menggunakan success/ error:

$http.get('/someURL').success(function(data, status, header, config) {
    // success handler
}).error(function(data, status, header, config) {
    // error handler
});
TheHippo
sumber
5
Terima kasih, tetapi pertanyaannya lebih tentang perbedaan fungsi apa yang dilakukan atau alasan mengapa keduanya ada jika mereka melakukan hal yang sama. Perbedaan cara menggunakannya bisa dipahami dari dokumen.
ejoubaud
39
Saya pribadi suka contoh kode pendek, dan saya mempostingnya di sini. Dokumen Angular kadang-kadang kehilangan contoh tepat pendek.
TheHippo
2
Penting untuk menyoroti fakta bahwa objek respons dari intisari pertama berisi "data, status, heade, dan konfigurasi" dari intisari kedua. Itu berarti bahwa objek respons memiliki satu tingkat kedalaman tambahan.
geoom
Apakah ada manfaat melewatkan nilai respons ke variabel data,status,header,confighanya dengan mengembalikan response?
ᴍᴀᴛᴛ ʙᴀᴋᴇʀ
27

.then () dapat diputus-putus dan akan menunggu sebelumnya .then () diselesaikan.

.success () dan .error () dapat dirantai, tetapi mereka semua akan menyala sekaligus (jadi tidak banyak yang menunjukkan hal itu)

.success () dan .error () hanya bagus untuk panggilan sederhana (pembuat mudah):

$http.post('/getUser').success(function(user){ 
   ... 
})

jadi Anda tidak perlu mengetik ini:

$http.post('getUser').then(function(response){
  var user = response.data;
})

Tetapi secara umum saya menangani semua kesalahan dengan .catch ():

$http.get(...)
    .then(function(response){ 
      // successHandler
      // do some stuff
      return $http.get('/somethingelse') // get more data
    })
    .then(anotherSuccessHandler)
    .catch(errorHandler)

Jika Anda perlu mendukung <= IE8 kemudian tulis .catch () dan .finally () seperti ini (metode yang dicadangkan di IE):

    .then(successHandler)
    ['catch'](errorHandler)

Contoh kerja:

Ini adalah sesuatu yang saya tulis dalam format yang lebih kode untuk menyegarkan ingatan saya tentang bagaimana semuanya berjalan dengan penanganan kesalahan dll

http://jsfiddle.net/nalberg/v95tekz2/

nawlbergs
sumber
Satu-satunya jawaban yang menunjukkan bagaimana "return-another-janji" bekerja
zjk
17

Hanya untuk penyelesaian, berikut adalah contoh kode yang menunjukkan perbedaan:

sukses \ kesalahan:

$http.get('/someURL')
.success(function(data, status, header, config) {
    // success handler
})
.error(function(data, status, header, config) {
    // error handler
});

kemudian:

$http.get('/someURL')
.then(function(response) {
    // success handler
}, function(response) {
    // error handler
})
.then(function(response) {
    // success handler
}, function(response) {
    // error handler
})
.then(function(response) {
    // success handler
}, function(response) {
    // error handler
}).
MichaelLo
sumber
hebat !, apakah Anda memiliki contoh di mana rangkaian dapat bermanfaat?
geoom
4
Idenya adalah bahwa pendekatan "maka" lebih berguna, karena Anda dapat lebih mudah menulis operasi asinkron satu demi satu.
MichaelLo
2

Pemberitahuan Resmi: keberhasilan dan kesalahan telah ditinggalkan, silakan gunakan metode standar maka sebagai gantinya.

Penghentian Pemberitahuan: keberhasilan dan kesalahan metode janji warisan $ http telah ditinggalkan. Gunakan metode standar maka sebagai gantinya. Jika $ httpProvider.useLegacyPromiseExtensions disetel ke false maka metode ini akan menghasilkan $ http / error lama.

tautan: https://code.angularjs.org/1.5.7/docs/api/ng/service/$http

tangkapan layar: melihat tangkapan layar

MagicBoy
sumber