Açısal HttpPromise: "başarı" / "hata" yöntemleri ile `` then '' argümanları arasındaki fark


177

AngularJS belgesine göre $http, aşağıdakileri döndürmeye çağırır :

Standard then yöntemi ve iki http'ye özgü yöntem ile bir promise nesnesi döndürür : başarı ve hata . Daha sonra yöntem, iki bağımsız değişken bir alan başarılı bir hata yanıt nesnesi ile çağrılır geri arama. Başarı ve hata isteği başarılı veya sırasıyla başarısız olduğunda çağrılacak bir işlev - yöntemler tek argüman alır. Bu işlevlere iletilen argümanlar, then yöntemine iletilen yanıt nesnesinin tahrip edilmiş temsilidir.

responseNesnenin bir durumda tahrip olması gerçeğinin yanı sıra,

  • argümanları olarak iletilmek üzere iletilen başarı / hata geri çağrıları promise.then
  • sözün promise.success/ promise.erroryöntemleri için argümanlar olarak iletilen geri çağrılar

Var mı? Görünüşte aynı geri çağrıları iletmenin bu iki farklı yolunun anlamı nedir?

Yanıtlar:


156

Not: Bu cevap aslında yanlış; aşağıdaki bir yorumda belirtildiği gibi, success () orijinal vaadi döndürür. Değişmeyeceğim; ve düzenlemek için OP'ye bırakın.


2 arasındaki en büyük fark, .then()çağrının bir geri arama .success()kaydetmenin daha geleneksel bir yolu olduğu ve geri arama kaydetmenin daha geleneksel bir yolu olduğu ( bir geri aramanın döndürdüğü bir değerle çözülmüş) bir söz vermesidir.

Vaat tabanlı geri aramalar ( .then()) vaatlerin zincirlenmesini kolaylaştırır (bir çağrı yapın, sonuçları yorumlayın ve sonra başka bir çağrı yapın, sonuçları yorumlayın, başka bir çağrı yapın vb.).

Bu .success()yöntem, çağrıyı zincirlemenize veya vaat API'sı ile çalışmanıza (örneğin, yönlendirme sırasında) ihtiyaç duymadığınızda akıcı, kullanışlı bir yöntemdir.

Kısacası:

  • .then() - söz API'sının tam gücü ancak biraz daha ayrıntılı
  • .success() - bir söz vermez, ancak biraz daha uygun sözdizimi sunar

44
Bir başka büyük fark olduğunu thenyanıtı - - ederken geri aramaları Tek bir argüman alan successve errorarguments-- olarak yanıtın bireysel bileşenlerini almak data, status, header, ve config.
Michelle Tilley

1
@BrandonTilley tamamen doğru, ama sorunun yazarı zaten anladım, bu yüzden burada tekrar etmem gerekmiyor gibi hissetmedim.
pkozlowski.opensource

45
Belgeler bu kadar açık bir şekilde söylemese .success()de, zincirin $http(...).success(...).error(...)mümkün olduğu için yöntemin orijinal $ http promise nesnesini döndürdüğünü çıkarabiliriz . Makul göründüğü gibi, tersi $http(...).error(...).success(...)de mümkünse, .error()orijinal vaat nesnesini de döndürmelidir. Ayırt edici farkı .then()bir döner olmasıdır yeni vaadi.
Pancar-Pancar

2
$ Http hizmetinin angular.js kaynak kodu: promise.success = function(fn) { promise.then(function(response) { fn(response.data, response.status, response.headers, config); }); return promise; };
Alex Che

6
Lütfen successkullanımdan kaldırıldığını unutmayın . Gönderen 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

Burada zaten bazı iyi cevaplar var. Ancak sunulan paralellikteki farkı eve götürmek faydalı olacaktır:

  • success() orijinal vaadi döndürür
  • then() yeni bir söz veriyor

then()Her çağrı yeni bir vaat döndürdüğünden, fark sıralı işlemleri yönlendirir.

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

success() işleyiciler aynı vaatle zincirlendiğinden paralel operasyonları yönlendirir.

$http(/*...*/).
  success(function parFunc1(data){/*...*/}).
  success(function parFunc2(data){/*...*/})
  1. $http.get()
  2. parFunc1(), parFunc2()paralel olarak

3
A'ya thenulaşıldığında döndürülen yeni vaat yanıtının successve erroryöntemlerinin kaybolmasına neden olduğunu unutmayın. Ayrıca, http hata yanıtları (örn. 404) için ilk thengiriş işleyiciye http.then(ok, err).then(ok, err)geçer, errancak aşağıdakiler okişleyiciye geçer . Temel http.success().error().success().error()olarak zincirlenebilir, ancak $ q vaatleri, özellikle söz konusu işlemin söz ve sırası ile (ve http istek işleme değil) oldukça farklıdır. Yakından bakana kadar bunu anlamakta zorlandım.
jimmont

1
@jimmont successve errorbir sözün normal API'si değiller, $ http () dönüş değerine cıvatalanırlar.
event_jr

Teşekkürler @event_jr bu benim için açık ve dokümanlarda çağrıldı. Ne kadar net değildi (benim için) $ q ve $ http nasıl farklı sorunları çözmek yanı sıra yeni sözler (aynı zamanda geçerek vs - (süper yararlı) cevabında belirtildiği gibi dönen olduğunu.
jimmont

1
JS tek iş parçacıklı olduğu için paralel olarak ne demek istiyorsun? İcra emrinin deterministik olmadığı anlamına mı geliyor?
Derek

2
@Derek, ikincisi successbirincisi yerine getirildikten sonra yerine getirilir, ancak ondan geri verilen herhangi bir söz çözülmeden önce ikincisi thenbekler. Eğer sözleri iade etmiyorsanız, o zaman her ikisi de aynı şekilde davranır.
Tamlyn

114

Basit GET isteği için bazı kod örnekleri. Belki de bu farkın anlaşılmasına yardımcı olur. Kullanma 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
});

success/ Kullanarak error:

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

5
Teşekkür ederim, ama soru daha çok bu işlevlerin ne iş yaptığı ya da her ikisinin de aynı şeyi yaparlarsa neden var olmaları ile ilgiliydi. Bunların kullanımındaki fark, doktordan anlaşılabilir.
ejoubaud

39
Ben şahsen kısa kod örneklerini seviyorum ve bu yüzden onları buraya gönderdim. Açısal dokümanlar bazen kısa kesin örnekleri kaçırırlar.
TheHippo

2
İlk öznenin yanıt nesnesinin ikinci özün "veri, durum, yığın ve yapılandırma" yı içerdiğini vurgulamak önemlidir. Bu, yanıt veren nesnelerin bir seviye derinliğe sahip olduğu anlamına gelir.
geoom

Yanıt değerlerinin data,status,header,configbasitçe geri dönmenin değişkenlerine aktarılmasının herhangi bir faydası var mı response?
ʙᴀᴋᴇʀ ʙᴀᴋᴇʀ

27

.then () zincirlenebilir ve önceki .then () öğesinin çözülmesini bekleyecektir.

.success () ve .error () zincirlenebilir, ancak hepsi bir kerede ateş edecekler (buna çok fazla işaret etmiyor)

.success () ve .error () basit çağrılar (kolay yapımcılar) için iyidir:

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

bu yüzden bunu yazmak zorunda değilsiniz:

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

Ama genellikle i .catch () ile tüm hataları işleyici:

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

<= IE8'i desteklemeniz gerekiyorsa .catch () ve .finally () yönteminizi şöyle yazın (IE'de ayrılmış yöntemler):

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

Çalışma Örnekleri:

İşte daha fazla codey formatında yazdığım bir şey var, hafızamı her şeyin nasıl ele alınacağıyla nasıl oynadığına dair yenilemek vb.

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


"Dönüş-başka bir söz" nasıl çalışır gösteren tek cevap
zjk

17

Sadece tamamlama için, farkları gösteren bir kod örneği:

başarı \ hatası:

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

sonra:

$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
}).

great !, birleştirmenin faydalı olabileceği bir örnek var mı?
geoom

4
Fikir, "o zaman" yaklaşımının daha yararlı olmasıdır, çünkü birbiri ardına asenkron işlemleri daha kolay yazabilirsiniz.
MichaelLo

2

Resmi Uyarı: başarı ve hata onaylanmadı, lütfen bunun yerine standardı sonra yöntemi kullanın.

Kullanımdan Kaldırılma Bildirimi: $ http eski söz verme yöntemlerinin başarısı ve hatası kullanımdan kaldırıldı. Bunun yerine standard ve sonra yöntemini kullanın. $ HttpProvider.useLegacyPromiseExtensions öğesi false olarak ayarlanırsa, bu yöntemler $ http / legacy hatası verir.

bağlantı: https://code.angularjs.org/1.5.7/docs/api/ng/service/$http

ekran görüntüsü: ekran görüntüsünü göster

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.