RxJS harita operatöründen hata nasıl atılır (açısal)


93

Bir koşula bağlı olarak gözlemlenebilir cihazımın harita operatöründen bir hata atmak istiyorum . Örneğin, doğru API verileri alınmazsa. Lütfen aşağıdaki koda bakın:

private userAuthenticate( email: string, password: string ) {
    return this.httpPost(`${this.baseApiUrl}/auth?format=json&provider=login`, {userName: email, password: password})
        .map( res => { 
            if ( res.bearerToken ) {
                return this.saveJwt(res.bearerToken); 
            } else {
                // THIS DOESN'T THROW ERROR --------------------
                return Observable.throw('Valid token not returned');
            }
        })
        .catch( err => Observable.throw(this.logError(err) )
        .finally( () => console.log("Authentication done.") );
}

Temel olarak kodda görebileceğiniz gibi, yanıt (res nesnesi) 'bearerToken' içermiyorsa, bir hata atmak istiyorum. Böylece aboneliğimde aşağıda belirtilen 2. parametreye (handleError) giriyor.

.subscribe(success, handleError)

Herhangi bir öneri?


4
Peki ya throw 'Valid token not returned';?
Günter Zöchbauer

Derleme başarısız
Hassan

Tam hata mesajı lütfen.
Günter Zöchbauer

2
Maalesef işe yaramıyor return throw 'message here'ama returnanahtar kelime olmadan çalışıyor . Mantıksal olarak doğru çalışıp çalışmadığını kontrol edeyim.
Hassan

Hata metni subscribeyöntemde alınmıyor .finally()ve akışta da tetikleniyor. (Ancak infaz durduruldu ki bu iyi bir şey)
Hassan

Yanıtlar:


141

Sadece hatayı map()operatörün içine atın . RxJS'deki tüm geri aramalar, yakalanacak ve ardından bir errorbildirim olarak gönderilecek şekilde, deneme-yakalama bloklarıyla sarılır .

Bu, hiçbir şey iade etmeyeceğiniz ve sadece hatayı atacağınız anlamına gelir:

map(res => { 
  if (res.bearerToken) {
    return this.saveJwt(res.bearerToken); 
  } else {
    throw new Error('Valid token not returned');
  }
})

throwError()(Eski Observable.throw()RxJS 5'te) sadece gönderdiği bir gözlemlenebilir olduğu errorbildirim ama map()dönmek umurumda değil. Bir Gözlemlenebilir'i iade etseniz bile map()ondan nextbildirim olarak iletilecektir .

Son olarak, muhtemelen kullanmanız gerekmiyor .catchError()(eski catch()RxJS 5 idi). Bir hata meydana geldiğinde herhangi bir yan etki yapmanız gerekiyorsa, örneğin kullanmak daha iyidir tap(null, err => console.log(err))(eski do()RxJS 5'te).

Oca 2019: RxJS 6 için güncellendi


1
Teşekkürler @martin - Evet, çözümünüz işe yarıyor. @ GünterZöchbauer'in de belirttiği gibi logError yöntemimde de bir sorun yaşadım. Ondan returnhata nesnesini almak zorunda kaldım ve şimdi mükemmel çalışıyor :) Teşekkürler!
Hassan

@martin: Burada .catch () neden sizi istemediğimizi açıklar mısınız?
Bob

1
@Bob Çünkü OP, catch()hatayı yalnızca günlüğe kaydetmek ve yeniden atmak için kullanıyordu ; bu, yalnızca bir yan etki gerçekleştirmek istiyorsanız (hatayı günlüğe kaydetmek istiyorsanız) gereksiz ve kullanımı daha kolaydo()
martin

1
Bu aynı mı return throwError(new Error('Valid token not returned'));?
Simon_Weaver

@Simon_Weaver hayır değil. return throwError()bir döndürür Observable<never>, bu sadece gözlemlenebilir akışı hiç geri dönmeden hemen keser.
Monica'yı

25

Gözlenemez gibi throw new Error()göründüğünüzü düşünüyorsanız throwError(...), switchMapbunun yerine ile kullanabilirsiniz map(fark switchMapyeni bir gözlemlenebilir döndürür):

// this is the import needed for throwError()
import { throwError } from 'rxjs';


// RxJS 6+ syntax
this.httpPost.pipe(switchMap(res => { 
   if (res.bearerToken) {
      return of(this.saveJwt(res.bearerToken)); 
   } 
   else {
      return throwError('Valid token not returned');  // this is 
   }
});

veya daha kısaca:

this.httpPost.pipe(switchMap(res => (res.bearerToken) ? 
                                    of(this.saveJwt(res.bearerToken)) : 
                                    throwError('Valid token not returned')
));

Davranış aynı olacak, sadece farklı sözdizimi.

Kelimenin tam anlamıyla, borudaki gözlemlenebilir http'den farklı bir gözlemlenebilirliğe 'geçiş' diyorsunuz, bu ya çıktı değerini sadece 'sarıyor' ya da yeni bir 'hata' gözlemlenebilir.

Koymayı unutmayın, ofaksi takdirde kafa karıştırıcı hata mesajları alırsınız.

Ayrıca, "switchMap" in güzelliği, eğer isterseniz, mantıkla yapılması gereken her ne olursa olsun, tamamen yeni bir komut "zinciri" döndürebilmenizdir saveJwt.


4
switchMapEşzamansız bir ififade olarak düşünmeye başladığımda - işler çok daha anlamlı hale geldi :-)
Simon_Weaver

3

Bu soru zaten cevaplanmış olsa da, kendi yaklaşımımı paylaşmak istiyorum (yukarıdan biraz farklı olsa da).

Neyin haritalamadan ayrı olarak döndürüleceğine karar veririm ve bunun tersi de geçerlidir. Bunun için en iyi operatörün hangisi olduğundan emin değilim, bu yüzden kullanacağım tap.

this.httpPost.pipe(
  tap(res => { 
    if (!res.bearerToken) {
      throw new Error('Valid token not returned');
    }
  }),
  map(res => this.saveJwt(res.bearerToken)),
);

dönüş değeri tapgöz ardı edilir. bu kod yazdığından farklı bir şey yapıyor
sf

Hala rxj'lere alışmaya başladım. SwitchMap kullanmak daha mı iyi? Biri farklı bir operatör önerebilir veya doğrudan düzenleyebilir mi?
christo8989

Bence önerilen throw new Error()şu ana kadarki en iyi seçenek
sf
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.